วิธีการส่ง ArrayList ไปยังพารามิเตอร์วิธีการ varargs?


236

โดยทั่วไปฉันมี ArrayList ของที่ตั้ง:

ArrayList<WorldLocation> locations = new ArrayList<WorldLocation>();

ด้านล่างนี้ฉันเรียกวิธีการดังต่อไปนี้:

.getMap();

พารามิเตอร์ในเมธอด getMap () คือ:

getMap(WorldLocation... locations)

ปัญหาที่ฉันมีคือฉันไม่แน่ใจว่าจะผ่านรายการ WHOLE locationsไปสู่วิธีการนั้นได้อย่างไร

ฉันพยายามแล้ว

.getMap(locations.toArray())

แต่ getMap ไม่ยอมรับเพราะไม่ยอมรับวัตถุ []

ตอนนี้ถ้าฉันใช้

.getMap(locations.get(0));

มันจะทำงานได้อย่างสมบูรณ์แบบ ... แต่ฉันจำเป็นต้องผ่านในสถานที่ทั้งหมด ... แน่นอนฉันสามารถให้เพิ่มlocations.get(1), locations.get(2)ฯลฯ แต่ขนาดของอาร์เรย์แตกต่างกันไป ฉันแค่ไม่คุ้นเคยกับแนวคิดทั้งหมดของArrayList

อะไรจะเป็นวิธีที่ง่ายที่สุดในการทำสิ่งนี้? ฉันรู้สึกเหมือนฉันไม่ได้คิดตรงๆตอนนี้


คำตอบ:


340

บทความที่มา: การส่งรายการเป็นอาร์กิวเมนต์ไปยังวิธีการ vararg


ใช้toArray(T[] arr)วิธีการ

.getMap(locations.toArray(new WorldLocation[locations.size()]))

(ใช้toArray(new WorldLocation[0])งานได้ แต่คุณจะจัดสรรอาเรย์ความยาวเป็นศูนย์โดยไม่มีเหตุผล)


นี่คือตัวอย่างที่สมบูรณ์:

public static void method(String... strs) {
    for (String s : strs)
        System.out.println(s);
}

...
    List<String> strs = new ArrayList<String>();
    strs.add("hello");
    strs.add("wordld");

    method(strs.toArray(new String[strs.size()]));
    //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

1
การดำเนินการนี้มีค่าใช้จ่ายเท่าใดในแง่ของหน่วยความจำและความเร็ว
mindreader

สิ่งนี้จะไม่ทำงานหากไม่มีการเตือนหากมีแม่แบบเพิ่มเติมที่เกี่ยวข้อง เช่นsomeMethod(someList.toArray(new ArrayList<Something>[someList.size()]))จะให้คำเตือนที่น่ารำคาญมากหากฟังก์ชั่นมีความยาวมากกว่าสองสามบรรทัด (เพราะคุณสามารถระงับมันได้ทั้งฟังก์ชั่นหรือคุณต้องสร้างอาเรย์ในขั้นตอนเพิ่มเติมและระงับการเตือนตัวแปรที่คุณ เก็บไว้
Qw3ry

23
เห็นได้ชัดว่าวิธีที่เร็วที่สุดคือให้ขนาดเป็นศูนย์มากกว่าขนาดของอาร์เรย์ กล่าวโดยสรุปก็คือค่าคงที่เวลาคอมไพล์ทำให้สามารถใช้วิธีการที่เหมาะสมที่สุดได้ shipilev.net/blog/2016/arrays-wisdom-ancients
geg

2
@JoshM Java ต้องการสิ่งต่าง ๆ มากมาย ;) ฉันยัง (มาจากพื้นหลัง C #) ตัวดำเนินการดัชนีพลาด การทำงานกับพจนานุกรมนั้นราบรื่นกว่าใน C # มากกว่าการทำงานกับ HashMaps ใน Java
ต่อ Lundberg

@PerLundberg - เห็นด้วยทั้งหมด นอกจากนี้นักพัฒนา C # เป็นหลักในปัจจุบันทำงานด้วย Java8 บางที 10/11 จะดีกว่า :-P
Josh M.

42

ใน Java 8:

List<WorldLocation> locations = new ArrayList<>();

.getMap(locations.stream().toArray(WorldLocation[]::new));

2
นี่คือ java voodoo แต่ดีกว่า java (8) voodoo .. ขอบคุณ!
granadaCoder

locations.toArray(WorldLocations[]::new)ดูเหมือนว่าจะใช้งานได้ตั้งแต่ java 11 (ไม่มี.stream())
Eran Medan

12

คำตอบที่เป็นที่ยอมรับน้อยกว่าโดยใช้ Guava:

.getMap(Iterables.toArray(locations, WorldLocation.class));

สามารถย่อให้สั้นลงได้อีกโดยนำเข้าสู่อาเรย์แบบคงที่:

import static com.google.common.collect.toArray;
// ...

    .getMap(toArray(locations, WorldLocation.class));

1

คุณทำได้:

getMap(locations.toArray(new WorldLocation[locations.size()]));

หรือ

getMap(locations.toArray(new WorldLocation[0]));

หรือ

getMap(new WorldLocation[locations.size()]);

@SuppressWarnings("unchecked") จำเป็นต้องลบคำเตือน ide


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