วิธีที่กระชับที่สุดในการแปลง Set <T> เป็น List <T>


201

ตัวอย่างเช่นฉันกำลังทำสิ่งนี้อยู่:

Set<String> setOfTopicAuthors = ....

List<String> list = Arrays.asList( 
    setOfTopicAuthors.toArray( new String[0] ) );

คุณสามารถเอาชนะสิ่งนี้ได้หรือไม่


2
ใช้java.util.Collection: O (0)
ทิม

@Carl ฉันต้องส่ง Set เป็นอินเทอร์เฟซของบุคคลที่สามซึ่งต้องการรายการ @Tim ฉันหวังว่าฉันจะเปลี่ยนอินเทอร์เฟซของบุคคลที่สามให้ใช้งานคอลเล็กชันได้
Jacques René Mesrine

1
ฉันเห็น; ยกเว้นข้อ จำกัด แปลก ๆ ฉันจะไปกับคำตอบของโรเจอร์ ถึงแม้ว่าคุณจะใช้รายชื่อจริงอีกครั้งฉันจะข้ามการกำหนดให้กับสิ่งใด ๆ (เช่นใช้ foo.api (ArrayList ใหม่ <String> (listOfTopicAuthors ใหม่)) แทน foo.api (รายการ))
คาร์ล

2
@ JacquesRenéMesrine: บรรทัดแรกของคำถามที่ทำให้เข้าใจผิด: คาดว่า: Set<String> setOfTopicAuthors = ....จริง:Set<String> listOfTopicAuthors = ....
realPK

หรือวิธีอื่นในการทำเช่นนั้นอาจมีList<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))รายละเอียดในคำตอบที่เชื่อมโยง
Naman

คำตอบ:


432
List<String> list = new ArrayList<String>(listOfTopicAuthors);

1
... และด้วยเหตุนี้จึงเป็นการท้าทายข้อตกลงรหัส Java: oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus

หลังจากนี้เมื่อฉันพยายามที่จะเข้าถึงองค์ประกอบรายการมันทำให้ฉันมีข้อผิดพลาด "java.lang.ClassCastException: java.lang.Integer ไม่สามารถส่งไปยัง java.lang.String" ..don; ไม่ทราบว่าทำไมมันง่าย list.get (int) นั่นคือ ... คำแนะนำใด ๆ
CoDe

2
ฉันเชื่อใน Java 7 ขึ้นไปคุณสามารถละเว้นพารามิเตอร์ type เพื่อArrayListให้ได้ผลลัพธ์: List<String> l = new ArrayList<>(listOfTopicAuthors); รัดกุมที่สุดโดยไม่ต้องใช้ไลบรารีภายนอก
Brett Duncavage

มันจะโยน NullPointerException ในกรณีที่listOfTopicAuthorsเป็นโมฆะ
w35l3y

91
List<String> l = new ArrayList<String>(listOfTopicAuthors);

4
สำหรับการตอบในนาทีเดียวกับคำตอบที่ยอมรับและไม่ได้รับเครดิต +1
jayeffkay

@Adamski ฉันจะจบลงด้วยรายการที่ดัชนีเริ่มต้นที่ 1 แทน 0, แก้ไขใด ๆ ?
แจ็ค

1
@ แจ็ค: นั่นไม่ใช่กรณีอย่างแน่นอน จาก Javadoc จาก java.util.List: "รายการ (เช่นอาร์เรย์ Java) ใช้ค่าศูนย์"
Adamski

@Adamski ขอบคุณสำหรับการตอบสนอง ฉันรู้ว่ารายการควรจะเป็นและเป็นศูนย์ซึ่งเป็นเหตุให้แปลกสำหรับฉัน หลังจากแปลงชุดของฉันเป็นรายการฉันไม่สามารถดำเนินการซ้ำ ๆ บน foreach, sort และอื่น ๆ ฉันได้รับ NullPointerException อย่างไรก็ตามเมื่อฉันคาดหวังว่ารายการของฉันไม่มีองค์ประกอบใดที่เป็นโมฆะและสิ่งเดียวที่ฉันสังเกตเห็นคือ ดัชนีเริ่มต้นที่ 1 อย่างไรก็ตามถ้าฉันเพิ่งสร้างรายการปกติดัชนีเริ่มต้นที่ 0 แปลก?
แจ็ค

1
@ แจ็ค: ฟังดูแปลกมาก หากคุณโพสต์รหัสของคุณเป็นคำถามแยกต่างหากฉันมั่นใจว่ามีบางคนสามารถช่วยเหลือคุณได้
Adamski

23

พิจารณาว่าเรามี Set<String> stringSetเราสามารถใช้ต่อไปนี้:

Java 10 (รายการที่แก้ไขไม่ได้)

List<String> strList = stringSet.stream().collect(Collectors.toUnmodifiableList());

Java 8 (รายการที่แก้ไขได้)

import static java.util.stream.Collectors.*;
List<String> stringList1 = stringSet.stream().collect(toList());

ตามเอกสารสำหรับวิธีการtoList()

ไม่มีการรับประกันเกี่ยวกับประเภทความไม่แน่นอนความต่อเนื่องของอนุกรมหรือความปลอดภัยของเธรดของรายการที่ส่งคืน หากต้องการการควบคุมมากกว่ารายการที่ส่งคืนให้ใช้ toCollection (ซัพพลายเออร์)

ดังนั้นหากเราต้องการการใช้งานที่เฉพาะเจาะจงเช่นArrayListเราสามารถทำให้เป็นเช่นนี้:

List<String> stringList2 = stringSet.stream().
                              collect(toCollection(ArrayList::new));

Java 8 (รายการที่แก้ไขไม่ได้)

เราสามารถใช้Collections::unmodifiableListวิธีการและห่อรายการที่ส่งคืนในตัวอย่างก่อนหน้านี้ นอกจากนี้เรายังสามารถเขียนวิธีการของเราเองเป็น:

class ImmutableCollector {
    public static <T> Collector<T, List<T>, List<T>> toImmutableList(Supplier<List<T>> supplier) {
            return Collector.of( supplier, List::add, (left, right) -> {
                        left.addAll(right);
                        return left;
                    }, Collections::unmodifiableList);
        }
}

จากนั้นใช้เป็น:

List<String> stringList3 = stringSet.stream()
             .collect(ImmutableCollector.toImmutableList(ArrayList::new)); 

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

    List<String> stringList4 = stringSet.stream().collect(collectingAndThen(
      toCollection(ArrayList::new),Collections::unmodifiableList));

หนึ่งในจุดที่จะต้องทราบคือว่าวิธีการที่Collections::unmodifiableListจะส่งกลับมุมมอง unmodifiable ของรายการที่ระบุตามเอกสาร คอลเล็กชันมุมมอง unmodifiable คือคอลเล็กชันที่ไม่สามารถแก้ไขได้และเป็นมุมมองไปยังคอลเล็กชันสำรอง โปรดทราบว่าการเปลี่ยนแปลงในคอลเลกชันสำรองอาจยังคงเป็นไปได้และหากเกิดขึ้นพวกเขาจะสามารถมองเห็นได้ผ่านมุมมองที่ไม่สามารถแก้ไขได้ แต่วิธีการเก็บCollectors.unmodifiableListกลับรายการเปลี่ยนรูปอย่างแท้จริงในการJava 10


ผมใช้วิธีนี้ในการแปลงSet<Double>ไปยังList<Doubleที่ตั้งมาจากLinkedHashMap's .keySet()วิธี คราสบอกผมว่ามีความไม่ตรงกันชนิดและที่ผมไม่สามารถแปลงจากไปObject List<Double>คุณบอกฉันได้ไหมว่าทำไมสิ่งนี้ถึงเกิดขึ้น ฉันได้มันโดยการร่าย แต่ฉันก็สงสัยว่าทำไมมันถึงเกิดขึ้น
Ungeheuer

1
ใช่เนื่องจากผู้พัฒนา Java ควรใช้คุณสมบัติ Java 8 มากขึ้นคำตอบนี้ดีกว่า 2 คำตอบข้างต้น
Shubham Pandey

13

ลองใช้ชุดนี้ :

Set<String> listOfTopicAuthors = .....
List<String> setList = new ArrayList<String>(listOfTopicAuthors); 

ลองใช้สำหรับแผนที่ :

Map<String, String> listOfTopicAuthors = .....
// List of values:
List<String> mapValueList = new ArrayList<String>(listOfTopicAuthors.values());
// List of keys:
List<String> mapKeyList = new ArrayList<String>(listOfTopicAuthors.KeySet());


0

ไม่แน่ใจจริงๆว่าคุณกำลังทำอะไรตรงตามบริบทของรหัสของคุณ แต่ ...

ทำไมถึงต้องสร้างlistOfTopicAuthorsตัวแปรทั้งหมด?

List<String> list = Arrays.asList((....).toArray( new String[0] ) );

".... " แสดงถึงชุดที่คุณเล่นไม่ว่าจะใหม่หรือมาจากที่อื่น

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