มีข้อได้เปรียบ (หรือแตกต่างกันมาก) ในการใช้ Arrays.asList (บางอย่าง) เหนือ Collections.singletonList (บางสิ่ง) เพื่อสร้างรายการที่มีหนึ่งรายการหรือไม่? หลังทำให้รายการที่ส่งคืนไม่เปลี่ยนรูปเช่นกัน
มีข้อได้เปรียบ (หรือแตกต่างกันมาก) ในการใช้ Arrays.asList (บางอย่าง) เหนือ Collections.singletonList (บางสิ่ง) เพื่อสร้างรายการที่มีหนึ่งรายการหรือไม่? หลังทำให้รายการที่ส่งคืนไม่เปลี่ยนรูปเช่นกัน
คำตอบ:
Collections.singletonList(something)
คือไม่เปลี่ยนรูปขณะที่Arrays.asList(something)
มีขนาดคงที่List
เป็นตัวแทนของอาร์เรย์ที่รายการและอาเรย์ได้รับการเข้าร่วมในกอง
Arrays.asList(something)
อนุญาตให้ทำการเปลี่ยนแปลงที่ไม่ใช่โครงสร้างซึ่งจะสะท้อนไปยังทั้งรายการและอาร์เรย์ที่ติดกัน มันพ่นUnsupportedOperationException
เพื่อเพิ่มลบองค์ประกอบแม้ว่าคุณจะสามารถตั้งค่าองค์ประกอบสำหรับดัชนีเฉพาะได้
การเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นกับรายการที่ส่งกลับโดยจะมีผลในCollections.singletonList(something)
UnsupportedOperationException
นอกจากนี้ความจุของรายการที่ส่งคืนCollections.singletonList(something)
จะเป็น1เสมอArrays.asList(something)
ซึ่งแตกต่างจากที่ความจุจะเท่ากับขนาดของอาร์เรย์ที่สำรองไว้
Collections.singletonList
แทน มันจะรู้ได้อย่างไรว่ามันปลอดภัยที่จะใช้? คุณเขียน (และตามการทดสอบของฉันมันเป็นความจริง) ซึ่งอาจทำให้เกิดข้อยกเว้นหากมีการแก้ไข (ตั้งค่า / ลบเป็นต้น) ...
ฉันจะเพิ่มว่ารายการเดี่ยวไม่ได้รับการสนับสนุนจากอาร์เรย์และมีการอ้างอิงถึงรายการนั้นเพียงรายการเดียว สันนิษฐานว่าจะใช้หน่วยความจำน้อยกว่าและอาจมีนัยสำคัญขึ้นอยู่กับจำนวนรายการที่คุณต้องการสร้าง
วิธีนี้Arrays.asList
จะส่งคืนรายการขนาดคงที่ซึ่งสนับสนุนโดยอาร์เรย์ที่ระบุ วิธีการส่งกลับตัวอย่างของArrayList
ซึ่งเป็นระดับคงที่ส่วนตัวที่ซ้อนกันขยายและไม่ได้AbstractList
java.util.ArrayList
นี้ชั้นคงให้การดำเนินงานของวิธีการไม่กี่เช่นset, indexOf, forEach, replaceAll
ฯลฯ แต่เมื่อเราเรียกใช้add
ก็มีการดำเนินการของตัวเองวิธีการค่อนข้างของมันไม่จากถูกเรียกซึ่งพ่นAbstractList
java.lang.UnsupportedOperationException
Collections.singletonList
ส่งกลับรายการที่ไม่เปลี่ยนรูปที่มีเพียงวัตถุที่ระบุและมันก็เป็น serializable เช่นกัน
หมายเหตุด้านข้างสำหรับรายการที่ไม่เปลี่ยนรูปโดยทั่วไปเราใช้Collections.unmodifiableList
ซึ่งส่งคืนมุมมองที่ไม่สามารถแก้ไขได้ของรายการที่ระบุ
List<String> srcList = Arrays.asList("Apple", "Mango", "Banana");
var fruits = new ArrayList<>(srcList);
var unmodifiableList = Collections.unmodifiableList(fruits);
fruits.set(0, "Apricot");
var modFruit = unmodifiableList.get(0);
System.out.println(modFruit); // prints Apricot
คอลเลกชันมุมมองที่ไม่สามารถปรับเปลี่ยนได้คือคอลเล็กชันที่ไม่สามารถปรับเปลี่ยนได้และยังเป็นมุมมองของคอลเล็กชันสำรอง โปรดทราบว่าการเปลี่ยนแปลงในคอลเล็กชันการสำรองอาจยังคงเป็นไปได้และหากเกิดขึ้นจะสามารถมองเห็นได้ผ่านมุมมองที่ไม่สามารถแก้ไขได้
เราสามารถมีรายการที่ไม่เปลี่ยนรูปจริงในJava 10และใหม่กว่า มีสองวิธีในการรับรายการที่ไม่สามารถแก้ไขได้อย่างแท้จริง :
var unmodifiableList = List.copyOf(srcList);
var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList());
หากมีการใช้ตัวแปรสองตัวนี้ค่าจะยังคงเป็น "Apple" และไม่ใช่ "Apricot" ตามเอกสารของJava 10 :
List.of
และList.copyOf
วิธีการโรงงานคงให้เป็นวิธีที่สะดวกในการสร้างรายการ unmodifiable อินสแตนซ์รายการที่สร้างโดยวิธีการเหล่านี้มีลักษณะดังต่อไปนี้:
- พวกเขาไม่สามารถแก้ไขได้ ไม่สามารถเพิ่มลบหรือเปลี่ยนองค์ประกอบได้ การเรียกใช้เมธอด mutator ใด ๆ ในรายการจะทำให้
UnsupportedOperationException
ถูกโยนทิ้งเสมอ อย่างไรก็ตามหากองค์ประกอบที่มีอยู่นั้นไม่แน่นอนอาจทำให้เนื้อหาของรายการมีการเปลี่ยนแปลง- พวกเขาไม่อนุญาตองค์ประกอบว่าง ความพยายามที่จะสร้างพวกเขามีองค์ประกอบ null
NullPointerException
ผลในการ- สามารถต่ออนุกรมได้หากองค์ประกอบทั้งหมดสามารถต่อเนื่องกันได้
- ลำดับขององค์ประกอบในรายการจะเหมือนกับลำดับของอาร์กิวเมนต์ที่ระบุหรือขององค์ประกอบในอาร์เรย์ที่จัดเตรียมไว้
value-based
พวกเขาเป็น ผู้โทรไม่ควรตั้งสมมติฐานเกี่ยวกับข้อมูลประจำตัวของอินสแตนซ์ที่ส่งคืน โรงงานมีอิสระในการสร้างอินสแตนซ์ใหม่หรือนำอินสแตนซ์ที่มีอยู่กลับมาใช้ใหม่ ดังนั้นการดำเนินการที่ไวต่อข้อมูลประจำตัวในอินสแตนซ์เหล่านี้ (อ้างอิงความเท่าเทียมกัน (==) รหัสแฮชข้อมูลประจำตัวและการซิงโครไนซ์) จึงไม่น่าเชื่อถือและควรหลีกเลี่ยง- พวกเขาจะต่อเนื่องตามที่ระบุไว้ในลำดับแบบฟอร์มหน้า
ImmutableList.of()
และLists.newArrayList()
ผสมได้เช่นกัน