Arrays.asList () เทียบกับ Collections.singletonList ()


140

มีข้อได้เปรียบ (หรือแตกต่างกันมาก) ในการใช้ Arrays.asList (บางอย่าง) เหนือ Collections.singletonList (บางสิ่ง) เพื่อสร้างรายการที่มีหนึ่งรายการหรือไม่? หลังทำให้รายการที่ส่งคืนไม่เปลี่ยนรูปเช่นกัน


8
คุณสามารถโยน Guava's ImmutableList.of()และLists.newArrayList()ผสมได้เช่นกัน
biziclop

นอกเหนือจากสิ่งนี้ฉันมี Collections.singletonList () ทำให้เกิดปัญหาเมื่อเมธอดส่งคืนรายการที่แก้ไขดาวน์สตรีมในภายหลัง
Howard Grimberg

1
Java 10 มีรายการที่ไม่เปลี่ยนรูปจริง: stackoverflow.com/a/52536126/1216775
akhil_mittal

คำตอบ:


214

Collections.singletonList(something)คือไม่เปลี่ยนรูปขณะที่Arrays.asList(something)มีขนาดคงที่Listเป็นตัวแทนของอาร์เรย์ที่รายการและอาเรย์ได้รับการเข้าร่วมในกอง

Arrays.asList(something)อนุญาตให้ทำการเปลี่ยนแปลงที่ไม่ใช่โครงสร้างซึ่งจะสะท้อนไปยังทั้งรายการและอาร์เรย์ที่ติดกัน มันพ่นUnsupportedOperationExceptionเพื่อเพิ่มลบองค์ประกอบแม้ว่าคุณจะสามารถตั้งค่าองค์ประกอบสำหรับดัชนีเฉพาะได้

การเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นกับรายการที่ส่งกลับโดยจะมีผลในCollections.singletonList(something)UnsupportedOperationException

นอกจากนี้ความจุของรายการที่ส่งคืนCollections.singletonList(something)จะเป็น1เสมอArrays.asList(something)ซึ่งแตกต่างจากที่ความจุจะเท่ากับขนาดของอาร์เรย์ที่สำรองไว้


ด้วยเหตุผลบางอย่าง IDE (Android Studio) บอกฉันว่าฉันควรใช้Collections.singletonListแทน มันจะรู้ได้อย่างไรว่ามันปลอดภัยที่จะใช้? คุณเขียน (และตามการทดสอบของฉันมันเป็นความจริง) ซึ่งอาจทำให้เกิดข้อยกเว้นหากมีการแก้ไข (ตั้งค่า / ลบเป็นต้น) ...
นักพัฒนา Android

64

ฉันจะเพิ่มว่ารายการเดี่ยวไม่ได้รับการสนับสนุนจากอาร์เรย์และมีการอ้างอิงถึงรายการนั้นเพียงรายการเดียว สันนิษฐานว่าจะใช้หน่วยความจำน้อยกว่าและอาจมีนัยสำคัญขึ้นอยู่กับจำนวนรายการที่คุณต้องการสร้าง


ลิงก์หรือรหัสใด ๆ เพื่อสำรองจุดประสิทธิภาพหน่วยความจำนี้หรือไม่ ฉันมี Arrays.asList (ONLY_ONE_OBJECT) นี้ที่เขียนบน codebase อย่างมากมายและต้องการทราบว่าการแทนที่ด้วย Collections.singletonList () จะทำให้ประสิทธิภาพของหน่วยความจำมีประสิทธิภาพหรือไม่?
Rahul Saini

Arrays.asList อ้างอิงอาร์เรย์ (ชัด): hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be44bff34df4/src/share/… Collections.singletonList: hg.openjdk.java.net/jdk8u/jdk8u/jdk / file / be44bff34df4 / src / share / …
Benjamin

14

วิธีนี้Arrays.asListจะส่งคืนรายการขนาดคงที่ซึ่งสนับสนุนโดยอาร์เรย์ที่ระบุ วิธีการส่งกลับตัวอย่างของArrayListซึ่งเป็นระดับคงที่ส่วนตัวที่ซ้อนกันขยายและไม่ได้AbstractList java.util.ArrayListนี้ชั้นคงให้การดำเนินงานของวิธีการไม่กี่เช่นset, indexOf, forEach, replaceAllฯลฯ แต่เมื่อเราเรียกใช้addก็มีการดำเนินการของตัวเองวิธีการค่อนข้างของมันไม่จากถูกเรียกซึ่งพ่นAbstractListjava.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และใหม่กว่า มีสองวิธีในการรับรายการที่ไม่สามารถแก้ไขได้อย่างแท้จริง :

  1. var unmodifiableList = List.copyOf(srcList);
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); หากมีการใช้ตัวแปรสองตัวนี้ค่าจะยังคงเป็น "Apple" และไม่ใช่ "Apricot"

ตามเอกสารของJava 10 :

List.ofและList.copyOfวิธีการโรงงานคงให้เป็นวิธีที่สะดวกในการสร้างรายการ unmodifiable อินสแตนซ์รายการที่สร้างโดยวิธีการเหล่านี้มีลักษณะดังต่อไปนี้:

  1. พวกเขาไม่สามารถแก้ไขได้ ไม่สามารถเพิ่มลบหรือเปลี่ยนองค์ประกอบได้ การเรียกใช้เมธอด mutator ใด ๆ ในรายการจะทำให้ UnsupportedOperationExceptionถูกโยนทิ้งเสมอ อย่างไรก็ตามหากองค์ประกอบที่มีอยู่นั้นไม่แน่นอนอาจทำให้เนื้อหาของรายการมีการเปลี่ยนแปลง
  2. พวกเขาไม่อนุญาตองค์ประกอบว่าง ความพยายามที่จะสร้างพวกเขามีองค์ประกอบ null NullPointerExceptionผลในการ
  3. สามารถต่ออนุกรมได้หากองค์ประกอบทั้งหมดสามารถต่อเนื่องกันได้
  4. ลำดับขององค์ประกอบในรายการจะเหมือนกับลำดับของอาร์กิวเมนต์ที่ระบุหรือขององค์ประกอบในอาร์เรย์ที่จัดเตรียมไว้
  5. value-basedพวกเขาเป็น ผู้โทรไม่ควรตั้งสมมติฐานเกี่ยวกับข้อมูลประจำตัวของอินสแตนซ์ที่ส่งคืน โรงงานมีอิสระในการสร้างอินสแตนซ์ใหม่หรือนำอินสแตนซ์ที่มีอยู่กลับมาใช้ใหม่ ดังนั้นการดำเนินการที่ไวต่อข้อมูลประจำตัวในอินสแตนซ์เหล่านี้ (อ้างอิงความเท่าเทียมกัน (==) รหัสแฮชข้อมูลประจำตัวและการซิงโครไนซ์) จึงไม่น่าเชื่อถือและควรหลีกเลี่ยง
  6. พวกเขาจะต่อเนื่องตามที่ระบุไว้ในลำดับแบบฟอร์มหน้า
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.