นากกายเรียงกล่องโทเคนจากหัวถึงท้ายแล้วพลิกมุมกลับบนโต๊ะมิ้นต์

SequencedCollection: เข้าถึงหัว-ท้ายและมุมกลับในชุดที่มีลำดับ

น้องกายEngineering

เคยต้องเขียน list.get(0) กับ list.get(list.size()-1) คนละสไตล์กับ Deque ไหม ผมเคย จนเจอ Sequenced Collections

ตั้งแต่ Java 21 ตามเอกสาร API ของ SequencedCollection คอลเลกชันที่มีลำดับการพบ (encounter order) ได้เมธอดหัว-ท้ายแบบเดียวกัน และมี reversed() เป็นมุมมองลำดับกลับ

ของที่ควรจำชื่อ

  • SequencedCollection: getFirst / getLast / addFirst / addLast / removeFirst / removeLast / reversed
  • SequencedSet: เหมือนด้านบนแต่สมาชิกไม่ซ้ำ เช่น LinkedHashSet
  • SequencedMap: จัดการแมปปิงหัว-ท้าย เช่น firstEntry / lastEntry / putFirst / putLast

ตัวอย่างด้านล่างเป็น code fragment สำหรับ JDK 21 ขึ้นไป จึงไม่อ้างว่ารันบน JDK 17 ของ quality gate แล้ว

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.SequencedCollection;
import java.util.SequencedMap;
import java.util.SequencedSet;

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.addFirst("a");
    list.addLast("c");
    list.add(1, "b");
    SequencedCollection<String> sequenced = list;
    if (!"a".equals(sequenced.getFirst()) || !"c".equals(sequenced.getLast())) {
      throw new IllegalStateException("list ends wrong: " + list);
    }
    List<String> reversed = sequenced.reversed().stream().toList();
    if (!List.of("c", "b", "a").equals(reversed)) {
      throw new IllegalStateException("reversed wrong: " + reversed);
    }

    SequencedSet<String> set = new LinkedHashSet<>();
    set.addFirst("one");
    set.addLast("two");
    set.addLast("three");
    if (!List.of("one", "two", "three").equals(List.copyOf(set))) {
      throw new IllegalStateException("set order wrong: " + set);
    }
    if (!"one".equals(set.getFirst()) || !"three".equals(set.getLast())) {
      throw new IllegalStateException("set ends wrong: " + set);
    }

    SequencedMap<String, Integer> map = new LinkedHashMap<>();
    map.putFirst("first", 1);
    map.putLast("last", 2);
    if (!"first".equals(map.firstEntry().getKey()) || !"last".equals(map.lastEntry().getKey())) {
      throw new IllegalStateException("map wrong: " + map);
    }
    System.out.println("sequenced ok " + list + " " + set + " " + map);
  }
}

Recap

  1. ใช้ API หัว-ท้ายชุดเดียวเมื่อคอลเลกชันมีลำดับชัด
  2. เลือก SequencedSet เมื่อห้ามซ้ำ และ SequencedMap เมื่อสนใจลำดับของแมปปิง
  3. จำว่า reversed() เป็นมุมมอง มีชีวิต ไม่ใช่สำเนาแยกเสมอไป
  4. ต้อง JDK 21 ขึ้นไปก่อนเรียกเมธอดเหล่านี้