ฉันจะเริ่มต้น ArrayList ด้วยศูนย์ทั้งหมดใน Java ได้อย่างไร


161

ดูเหมือนว่าarraylistจะไม่ทำงานเพื่อ presising:

// presizing 

ArrayList<Integer> list = new ArrayList<Integer>(60);

หลังจากนั้นเมื่อฉันพยายามเข้าถึง:

list.get(5) 

แทนที่จะกลับ 0 มันจะพ่นIndexOutOfBoundsException: ดัชนี 5 ออกจากขอบเขตสำหรับความยาว 0

มีวิธีการเริ่มต้นองค์ประกอบทั้งหมดถึง 0 ของขนาดที่แน่นอนเช่น C ++ อะไร?


4
Javadoc ของ Constructor นั้นระบุว่าจะสร้าง "รายการว่าง" มันกำลังทำงานอยู่
ColinD

คำตอบ:


429

จำนวนเต็มที่ส่งผ่านไปยังตัวสร้างแสดงถึงความสามารถเริ่มต้นของมันคือจำนวนขององค์ประกอบที่สามารถเก็บไว้ก่อนที่จะต้องปรับขนาดอาร์เรย์ภายในของมัน (และไม่มีอะไรจะทำอย่างไรกับจำนวนองค์ประกอบเริ่มต้นในรายการ)

ในการเริ่มต้นรายการด้วย 60 ศูนย์ให้ทำ:

List<Integer> list = new ArrayList<Integer>(Collections.nCopies(60, 0));

หากคุณต้องการสร้างรายการที่มีวัตถุต่าง ๆ 60 รายการคุณสามารถใช้ Stream API ด้วยรายการSupplierต่อไปนี้:

List<Person> persons = Stream.generate(Person::new)
                             .limit(60)
                             .collect(Collectors.toList());

1
นั้นดีกว่าโซลูชันของฉัน (แม้แต่รุ่นที่ปรับปรุงแล้วที่ใช้งานได้จริง) ฉันจะแนะนำไม่ได้ทำใหม่ออกมาจากมันแม้ว่าและแทนเพียงโปรแกรมที่จะArrayList Listนั่นเป็นการตัดสินใจที่จะทิ้งไว้กับ OP แน่นอน
corsiKa

6
รายการที่ส่งคืนโดยnCopiesไม่เปลี่ยนรูปดังนั้นการสร้างใหม่ArrayListอาจเป็นความคิดที่ดี
aioobe

4
ระวังว่าเมื่อใช้nCopiesกับวัตถุที่ซับซ้อนการเก็บรวบรวมจะไม่สร้างอินสแตนซ์ที่มีวัตถุต่าง ๆ 60 ชิ้น แต่จะใช้วัตถุเดียวกัน 60 ครั้ง ดังนั้นให้ใช้สิ่งนี้เป็นพื้นฐานเท่านั้น
Membersound

1
@ membersound ฉันสามารถนึกถึงหลาย ๆ สถานการณ์ที่nCopiesมีประโยชน์กับประเภทการอ้างอิง: อ็อบเจกต์ที่ไม่เปลี่ยนรูปเช่นสตริง, รูปแบบวัตถุโมฆะ, ค่าคงที่ enum, ... อย่างไรก็ตามฉันได้อัพเดตคำตอบด้วยวิธีแก้ปัญหาสำหรับการสร้างวัตถุ 60 ชนิด
aioobe

@aioobe ฉันรู้ว่ามีหลายสถานการณ์ที่ ncopies มีประโยชน์ ฉันแค่อยากจะเพิ่มสิ่งนี้เมื่อฉันลอง ncopies ด้วยวัตถุที่ไม่แน่นอนและรู้สึกประหลาดใจที่มันไม่ทำงานอย่างที่ฉันคาดไว้ ในกรณีที่ทุกคนพยายามทำงานเดียวกัน ขอบคุณสำหรับการอัปเดต!
membersound

12
// apparently this is broken. Whoops for me!
java.util.Collections.fill(list,new Integer(0));

// this is better
Integer[] data = new Integer[60];
Arrays.fill(data,new Integer(0));
List<Integer> list = Arrays.asList(data);

2
รายการนี้กรอกด้วยรายการที่มีอยู่เท่านั้น มันจะไม่เริ่มต้นมันด้วยองค์ประกอบตามที่ต้องการ
WhiteFang34

สิ่งนี้จะไม่เติมรายการด้วย 60 ศูนย์
aioobe

แม้ว่ามันจะสร้างวัตถุ 60 ที่มันไม่จำเป็นต้องสร้างใด ๆ
ColinD

1
@Frost: คุณจะได้รับIndexOutOfBoundsExceptionกับList<Integer> list = new ArrayList<Integer>(60); Collections.fill(list, new Integer(0)); list.get(5);
WhiteFang34

1
Arrays.asListสร้างรายการListที่ไม่อนุญาตให้เพิ่มหรือลบดังนั้นจึงไม่เหมือนกับที่ OP ต้องการ มันจะทำงานถ้าสิ่งที่คุณต้องทำคือsetแต่คุณอาจจะใช้อาร์เรย์ในกรณีนั้นดีกว่า
ColinD

8

60 ที่คุณกำลังผ่านไปเป็นเพียงความจุเริ่มต้นสำหรับการจัดเก็บข้อมูลภายใน มันเป็นคำใบ้ว่าคุณคิดว่ามันใหญ่แค่ไหน แต่ก็ไม่ได้ จำกัด อยู่แค่นั้น หากคุณต้องการตั้งค่าล่วงหน้าคุณจะต้องตั้งค่าด้วยตนเองเช่น:

for (int i = 0; i < 60; i++) {
    list.add(0);
}

4

การใช้งาน Java 8 (รายการเริ่มต้นด้วย60ศูนย์) :

List<Integer> list = IntStream.of(new int[60])
                    .boxed()
                    .collect(Collectors.toList());
  • new int[N] - สร้างอาร์เรย์ที่เต็มไปด้วยเลขศูนย์และความยาว N
  • boxed() - แต่ละองค์ประกอบที่บรรจุอยู่ในจำนวนเต็ม
  • collect(Collectors.toList()) - รวบรวมองค์ประกอบของกระแส

0

มันไม่ใช่แบบนั้นหรอก. ArrayList เพียงแค่ใช้อาร์เรย์เป็นตัวช่วยภายใน หากคุณเพิ่มองค์ประกอบมากกว่า 60 รายการจะมีการเอ็กซเรย์อาร์เรย์ คุณสามารถเพิ่มองค์ประกอบให้กับอาร์เรย์นี้ได้มากเท่าที่คุณมี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.