1. บทนำ
ในการเขียนโปรแกรมด้วย Java, List เป็นหนึ่งในโครงสร้างข้อมูลที่ใช้บ่อยและสำคัญที่สุด การใช้ List ช่วยให้คุณสามารถเก็บรายการหลายรายการตามลำดับและดำเนินการต่างๆ เช่น การเพิ่ม การลบ และการค้นหาองค์ประกอบตามต้องการได้อย่างง่ายดาย。
อย่างไรก็ตาม เพื่อใช้ List ได้อย่างมีประสิทธิภาพ สิ่งสำคัญคือต้องเข้าใจวิธีการเริ่มต้นใช้งานอย่างถ่องแท้ การเริ่มต้นที่ไม่ถูกต้องอาจทำให้เกิดข้อผิดพลาดหรือบั๊กที่ไม่คาดคิด และส่งผลกระทบอย่างมากต่อความสามารถในการอ่านและบำรุงรักษา。
ในบทความนี้ เราจะมุ่งเน้นหัวข้อ “การเริ่มต้น List ใน Java” และอธิบายทุกอย่างตั้งแต่ วิธีการเริ่มต้นพื้นฐานที่เป็นมิตรกับผู้เริ่มต้น ไปจนถึงเทคนิคเชิงปฏิบัติและข้อผิดพลาดทั่วไป เรายังครอบคลุมความแตกต่างระหว่างเวอร์ชัน Java และแนวปฏิบัติที่ดีที่สุดตามสถานการณ์การเขียนโค้ดในโลกจริง。
ไม่ว่าคุณจะเพิ่งเริ่มเรียน Java หรือใช้ List เป็นประจำอยู่แล้ว นี่เป็นโอกาสที่ดีในการทบทวนและจัดระเบียบรูปแบบการเริ่มต้นที่แตกต่างกัน
ส่วนคำถามที่พบบ่อย (FAQ) ถูกให้ไว้ที่ท้ายเพื่อช่วยแก้ไขคำถามและปัญหาทั่วไป。
2. วิธีการเริ่มต้น List พื้นฐาน
เมื่อเริ่มใช้ List ใน Java ขั้นตอนแรกคือการสร้าง “List ว่าง” ซึ่งหมายถึงการเริ่มต้น List ที่นี่ เราจะอธิบายวิธีการเริ่มต้นพื้นฐานโดยใช้การนำไปใช้งานที่พบบ่อยที่สุด คือ ArrayList。
2.1 การสร้าง List ว่างด้วย new ArrayList<>()
วิธีการเริ่มต้นที่ใช้บ่อยที่สุดคือ new ArrayList<>() ซึ่งเขียนดังนี้:
List<String> list = new ArrayList<>();
นี่คือการสร้าง List ว่างที่ไม่มีองค์ประกอบใดๆ
ประเด็นสำคัญ:
Listเป็นอินเทอร์เฟซ ดังนั้นคุณต้องสร้างอินสแตนซ์ของคลาสคอนกรีต เช่นArrayListหรือLinkedList.- โดยทั่วไป แนะนำให้ประกาศตัวแปรเป็น
Listเพื่อความยืดหยุ่น。
2.2 การเริ่มต้นด้วยความจุเริ่มต้นที่กำหนด
หากคุณคาดว่าจะเก็บข้อมูลจำนวนมากหรือรู้จำนวนองค์ประกอบแล้ว การกำหนดความจุเริ่มต้นจะช่วยเพิ่มประสิทธิภาพ
ตัวอย่าง:
List<Integer> numbers = new ArrayList<>(100);
นี่คือการสำรองพื้นที่สำหรับ 100 องค์ประกอบภายใน ลดต้นทุนการปรับขนาดเมื่อเพิ่มรายการและปรับปรุงประสิทธิภาพ
2.3 การเริ่มต้น LinkedList
คุณยังสามารถใช้ LinkedList ตามความต้องการได้ การใช้งานเกือบเหมือนกัน:
List<String> linkedList = new LinkedList<>();
LinkedList มีประสิทธิภาพโดยเฉพาะในสถานการณ์ที่องค์ประกอบถูกเพิ่มหรือลบบ่อยๆ
Java ทำให้การเริ่มต้น List ว่างทำได้ง่ายโดยใช้ new ArrayList<>() หรือ new LinkedList<>()。
3. การสร้าง List ด้วยค่าต้นเริ่ม
ในหลายกรณี คุณอาจต้องการสร้าง List ที่มีค่าต้นเริ่มอยู่แล้ว ด้านล่างคือรูปแบบการเริ่มต้นที่พบบ่อยที่สุดและลักษณะของ它们。
3.1 การใช้ Arrays.asList()
หนึ่งในวิธีที่ใช้บ่อยที่สุดใน Java คือ Arrays.asList()。
ตัวอย่าง:
List<String> list = Arrays.asList("A", "B", "C");
นี่คือการสร้าง List ด้วยค่าต้นเริ่ม
หมายเหตุสำคัญ:
- List ที่คืนค่าจะมีขนาดคงที่ และไม่สามารถเปลี่ยนความยาวได้ การเรียก
add()หรือremove()จะทำให้เกิดUnsupportedOperationException. - การแทนที่องค์ประกอบ (ด้วย
set()) อนุญาตให้ทำได้。
3.2 การใช้ List.of() (Java 9+)
ตั้งแต่ Java 9 เป็นต้นไป List.of() ช่วยให้สร้างList ที่ไม่สามารถเปลี่ยนแปลงได้ ได้อย่างง่ายดาย:
List<String> list = List.of("A", "B", "C");
ลักษณะ:
- List ที่ไม่สามารถเปลี่ยนแปลงได้อย่างสมบูรณ์—
add(),set()และremove()ถูกห้ามทั้งหมด. - อ่านง่ายมากและเหมาะสำหรับค่าคงที่。
3.3 การสร้าง List ที่สามารถเปลี่ยนแปลงได้จาก Arrays.asList()
หากคุณต้องการ List ที่มีค่าต้นเริ่มแต่ต้องการแก้ไขในภายหลัง วิธีนี้มีประโยชน์:
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
นี่คือการสร้าง List ที่สามารถเปลี่ยนแปลงได้。
add()และremove()ทำงานตามปกติ。
3.4 Double-Brace Initialization
เทคนิคขั้นสูงที่ใช้อนิเมชัสคลาส:
List<String> list = new ArrayList<>() {{
add("A");
add("B");
add("C");
}};
ลักษณะและคำเตือน:
- สร้างโค้ดที่กระชับแต่แนะนำคลาสนิรนาม ทำให้เกิดภาระเพิ่มเติมและอาจเกิดการรั่วของหน่วยความจำ.
- ใช้เฉพาะสำหรับการสาธิตอย่างรวดเร็วหรือโค้ดทดสอบ; ไม่แนะนำสำหรับการใช้งานจริง.
นี้แสดงว่า Java มีวิธี ๆ ในการสร้าง List พร้อมค่าตั้งต้นตามความต้องการของคุณ.
5. การเปรียบเทียบและเกณฑ์การเลือก
Java มีวิธีการเริ่มต้น List หลากหลาย และการเลือกที่ดีที่สุดขึ้นอยู่กับ กรณีการใช้งาน ส่วนนี้สรุปแต่ละวิธีและอธิบายว่าเมื่อใดควรเลือกใช้.
5.1 List ที่เปลี่ยนแปลงได้ vs List ที่ไม่เปลี่ยนแปลงได้
- List ที่เปลี่ยนแปลงได้
- สามารถเพิ่ม, ลบ หรือแก้ไของค์ประกอบได้.
- ตัวอย่าง:
new ArrayList<>(),new ArrayList<>(Arrays.asList(...)) - เหมาะสำหรับการดำเนินการแบบไดนามิกหรือการเพิ่มรายการในลูป.
- List ที่ไม่เปลี่ยนแปลงได้
- ไม่สามารถเพิ่ม, ลบ หรือแก้ไขได้.
- ตัวอย่าง:
List.of(...),Collections.singletonList(...),Collections.nCopies(...) - เหมาะสำหรับค่าคงที่หรือการส่งค่าที่ปลอดภัย.
5.2 ตารางเปรียบเทียบของวิธีทั่วไป
| Method | Mutability | Java Version | Characteristics / Use Cases |
|---|---|---|---|
new ArrayList<>() | Mutable | All Versions | Empty List; add elements freely |
Arrays.asList(...) | Fixed Size | All Versions | Has initial values but size cannot change |
new ArrayList<>(Arrays.asList(...)) | Mutable | All Versions | Initial values + fully mutable; widely used |
List.of(...) | Immutable | Java 9+ | Clean immutable List; no modifications allowed |
Collections.singletonList(...) | Immutable | All Versions | Immutable List with a single value |
Collections.nCopies(n, obj) | Immutable | All Versions | Initialize with n identical values; useful for testing |
Stream.generate(...).limit(n) | Mutable | Java 8+ | Flexible pattern generation; good for random or sequential data |
5.3 แนะนำรูปแบบการเริ่มต้นตามกรณีการใช้งาน
- เมื่อคุณต้องการ List ว่างเปล่าเท่านั้น
new ArrayList<>()- เมื่อคุณต้องการค่าตั้งต้นและต้องการแก้ไขต่อไป
newList<>(Arrays.asList(...))- เมื่อใช้เป็นค่าคงที่โดยไม่มีการแก้ไข
List.of(...)(Java 9+)Collections.singletonList(...)- เมื่อคุณต้องการจำนวนค่าที่เหมือนกันคงที่
Collections.nCopies(n, value)- เมื่อค่าต้องถูกสร้างแบบไดนามิก
Stream.generate(...).limit(n).collect(Collectors.toList())

5.4 หมายเหตุสำคัญ
- การพยายามแก้ไข List ที่ไม่เปลี่ยนแปลงหรือขนาดคงที่จะทำให้เกิดข้อยกเว้น.
- เลือกวิธีที่เหมาะสมกับความต้องการการเปลี่ยนแปลงและเวอร์ชันของ Java ของคุณ.
การเลือกวิธีการเริ่มต้นที่เหมาะสมจะป้องกัน บั๊กที่ไม่ตั้งใจ และเพิ่มความอ่านง่ายและความปลอดภัย.
6. ข้อผิดพลาดทั่วไปและวิธีแก้ไข
ข้อผิดพลาดบางอย่างมักเกิดขึ้นบ่อยเมื่อเริ่มต้นหรือใช้ List ใน Java ต่อไปนี้คือตัวอย่างทั่วไปและวิธีแก้ไขของพวกมัน.
6.1 UnsupportedOperationException
สถานการณ์ทั่วไป:
- เรียก
add()หรือremove()บน List ที่สร้างจากArrays.asList(...) - แก้ไข List ที่สร้างจาก
List.of(...),Collections.singletonList(...)หรือCollections.nCopies(...)
ตัวอย่าง:
List<String> list = Arrays.asList("A", "B", "C");
list.add("D"); // Throws UnsupportedOperationException
สาเหตุ:
- วิธีเหล่านี้สร้าง List ที่ไม่สามารถเปลี่ยนขนาดหรือเป็นแบบไม่เปลี่ยนแปลงทั้งหมด.
วิธีแก้:
- ห่อด้วย List ที่เปลี่ยนแปลงได้:
new ArrayList<>(Arrays.asList(...))
6.2 NullPointerException
สถานการณ์ทั่วไป:
- เข้าถึง List ที่ไม่เคยถูกกำหนดค่า
ตัวอย่าง:
List<String> list = null;
list.add("A"); // NullPointerException
สาเหตุ:
- มีการเรียกเมธอดบนอ้างอิงที่เป็น
null.
วิธีแก้:
- ควรกำหนดค่าเสมอก่อนใช้งาน:
List<String> list = new ArrayList<>();
6.3 ปัญหาเกี่ยวกับประเภท
- การสร้าง List โดยไม่มี generic จะเพิ่มความเสี่ยงของข้อผิดพลาดประเภทในเวลารัน.
Example:
List list = Arrays.asList("A", "B", "C"); Integer i = (Integer) list.get(0); // ClassCastException
วิธีแก้:
- ควรใช้ generic เสมอเมื่อเป็นไปได้.
การเข้าใจข้อผิดพลาดทั่วไปเหล่านี้จะช่วยให้คุณ หลีกเลี่ยงปัญหาเมื่อเริ่มต้นหรือใช้ List.
7. สรุป
บทความนี้อธิบายวิธีการเริ่มต้น List ต่าง ๆ ใน Java และวิธีเลือกวิธีที่เหมาะสม
เราครอบคลุม:
- การสร้าง List ว่างพื้นฐาน โดยใช้
new ArrayList<>()และnew LinkedList<>() - List ที่มีค่าเริ่มต้น โดยใช้
Arrays.asList(),List.of(), และnew ArrayList<>(Arrays.asList(...)) - รูปแบบการเริ่มต้นพิเศษ เช่น
Collections.singletonList(),Collections.nCopies(), และStream.generate() - ความแตกต่างสำคัญระหว่าง List ที่เปลี่ยนแปลงได้และไม่เปลี่ยนแปลงได้
- ข้อผิดพลาดทั่วไปและการจัดการข้อผิดพลาด
แม้ว่าการเริ่มต้น List จะดูง่าย แต่การทำความเข้าใจความแตกต่างเหล่านี้และการเลือกวิธีที่เหมาะสมเป็นสิ่งสำคัญสำหรับการเขียนโค้ดที่ปลอดภัยและมีประสิทธิภาพ
8. คำถามที่พบบ่อย (FAQ)
Q1: ฉันสามารถเพิ่มองค์ประกอบลงใน List ที่สร้างด้วย Arrays.asList() ได้หรือไม่?
A1: ไม่ได้ Arrays.asList() คืนค่า List ขนาดคงที่ การเรียก add() หรือ remove() จะทำให้เกิด UnsupportedOperationException ใช้ new ArrayList<>(Arrays.asList(...)) เพื่อให้ได้ List ที่เปลี่ยนแปลงได้
Q2: ความแตกต่างระหว่าง List.of() กับ Arrays.asList() คืออะไร?
List.of()(Java 9+) → ไม่เปลี่ยนแปลงได้อย่างสมบูรณ์; แม้set()ก็ไม่อนุญาตArrays.asList()→ ขนาดคงที่แต่อนุญาตให้ใช้set()
Q3: ควรใช้ Double‑Brace Initialization หรือไม่?
A3: ไม่แนะนำเนื่องจากมันสร้างคลาสนิรนามและอาจทำให้เกิดการรั่วของหน่วยความจำ ใช้การเริ่มต้นแบบมาตรฐานแทน
Q4: ประโยชน์ของการระบุความจุเริ่มต้นคืออะไร?
A4: จะลดการปรับขนาดภายในเมื่อเพิ่มหลายองค์ประกอบ ทำให้ประสิทธิภาพดีขึ้น
Q5: ควรใช้ generic เสมอเมื่อเริ่มต้น List หรือไม่?
A5: แน่นอน การใช้ generic ช่วยเพิ่มความปลอดภัยของประเภทและป้องกันข้อผิดพลาดในขณะรันไทม์
Q6: จะเกิดอะไรขึ้นหากใช้ List โดยไม่ได้ทำการเริ่มต้น?
A6: การเรียกใช้เมธอดใด ๆ จะทำให้เกิด NullPointerException ควรเริ่มต้นก่อนเสมอ
Q7: มีความแตกต่างของเวอร์ชันในการเริ่มต้น List หรือไม่?
A7: มี List.of() มีให้ใช้เฉพาะใน Java 9 ขึ้นไปเท่านั้น

