นากกายต้นฉบับกำลังหมุนถาดช่องข้อมูลวงกลมบนโต๊ะทำงานสีมิ้นต์

Java Collections.rotate: หมุนลำดับโดยไม่สร้าง list ใหม่

พี่โชว์Engineering

Collections.rotate เลื่อนสมาชิกใน list แบบ in place: distance บวกไปทางขวา ลบไปทางซ้าย และค่าที่เกินขนาดจะถูกคิดแบบวงกลมครับ เหมือนหมุนถาดซูชิทั้งสาย ไม่ได้ยกอาหารไปวางในถาดใหม่

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        var values = new ArrayList<>(List.of("A", "B", "C", "D"));
        Collections.rotate(values, 1);
        assert values.equals(List.of("D", "A", "B", "C"));

        Collections.rotate(values, -2);
        assert values.equals(List.of("B", "C", "D", "A"));

        Collections.rotate(values, 8);
        assert values.equals(List.of("B", "C", "D", "A"));

        var empty = new ArrayList<String>();
        Collections.rotate(empty, 3);
        assert empty.isEmpty();
    }
}

Mutation เป็นส่วนหนึ่งของ contract

List ต้องรองรับ set; List.of(...) เป็น immutable จึงต้อง copy เป็น ArrayList ก่อน หากผู้เรียกต้องรักษาลำดับเดิม ให้สร้างสำเนาอย่างตั้งใจและตั้งชื่อผลลัพธ์ให้สื่อว่าคือ rotated copy

สำหรับ queue ที่หมุนบ่อย ArrayDeque อาจเหมาะกว่า เพราะย้ายหัวท้ายได้ตรง semantics ส่วน rotate เด่นเมื่อเรามี list อยู่แล้วและต้อง reorder ครั้งคราว

Recap

  • บวกหมุนขวา ลบหมุนซ้าย
  • distance ถูก normalize ตามขนาด
  • ใช้ mutable list เท่านั้น
  • เลือก deque หากงานหลักคือหมุนคิวซ้ำ ๆ