Die prägnanteste Methode zum Konvertieren eines Sets <T> in eine Liste <T>

201

Zum Beispiel mache ich gerade Folgendes:

Set<String> setOfTopicAuthors = ....

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

Kannst du das schlagen?

Jacques René Mesrine
quelle
2
Verwenden Sie java.util.Collection: O (0)
Tim
@Carl, ich muss das Set an eine Schnittstelle eines Drittanbieters senden, für die eine Liste erforderlich ist. @ Tim Ich wünschte, ich könnte die Schnittstelle eines Drittanbieters ändern, um Collection zu verwenden.
Jacques René Mesrine
1
Aha; Abgesehen von merkwürdigen Einschränkungen würde ich Rogers Antwort folgen. Wenn Sie die Liste nicht tatsächlich erneut verwenden, würde ich die Zuweisung überspringen (dh foo.api (neue ArrayList <String> (listOfTopicAuthors)) anstelle von foo.api (Liste) verwenden).
Carl
2
@ JacquesRenéMesrine: Erste Zeile des fraglichen Codes ist irreführend: Erwartet: Set<String> setOfTopicAuthors = ....Tatsächlich:Set<String> listOfTopicAuthors = ....
realPK
Oder Sie können dies auch List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))in der verknüpften Antwort beschreiben.
Naman

Antworten:

432
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
quelle
1
... und sich damit radikal den Java-Code-Konventionen widersetzen : oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus
Danach, als ich versuchte, auf das Listenelement zuzugreifen, gab es den Fehler "java.lang.ClassCastException: java.lang.Integer kann nicht in java.lang.String umgewandelt werden". Ich weiß nicht warum. Es ist einfach list.get (int) das war's ... irgendein Vorschlag?
CoDe
2
Ich glaube an Java 7 und höher. Sie können den Typparameter weglassen, um ArrayListFolgendes zu erhalten: List<String> l = new ArrayList<>(listOfTopicAuthors); Am prägnantesten, ohne eine externe Bibliothek zu verwenden?
Brett Duncavage
Es wird eine NullPointerException ausgelöst, falls listOfTopicAuthorsnull ist.
w35l3y
91
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Adamski
quelle
4
für die Antwort in der gleichen Minute wie die akzeptierte Antwort und nicht die Gutschrift erhalten. +1
Jayeffkay
@Adamski Am Ende habe ich eine Liste, deren Index bei 1 statt bei 0 beginnt.
Jack
1
@ Jack: Das wird definitiv nicht der Fall sein. Aus dem Javadoc von java.util.List: "Listen (wie Java-Arrays) basieren auf Null."
Adamski
@ Adamski Danke für die Antwort. Ich weiß, dass Listen auf Null basieren sollten und sind, weshalb dies für mich so seltsam ist. Nachdem ich meinen Satz in eine Liste konvertiert habe, kann ich keine iterative Operation für jeden, jede Sortierung usw. ausführen. Ich erhalte jedoch eine NullPointerException. Wenn ich jedoch erwarte, dass meine Liste null ist, ist keines der Elemente null, und das einzig Seltsame ist, dass das Index beginnt bei 1. Wenn ich jedoch nur eine normale Liste erstelle, beginnt der Index bei 0. Seltsam?
Jack
1
@ Jack: Das klingt sehr komisch. Wenn Sie Ihren Code als separate Frage veröffentlichen, kann Ihnen sicher jemand weiterhelfen.
Adamski
23

In Anbetracht dessen, was wir haben Set<String> stringSet, können wir Folgendes verwenden:

Java 10 (nicht veränderbare Liste)

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

Java 8 (Änderbare Listen)

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

Gemäß dem Dokument für die MethodetoList()

Es gibt keine Garantie für den Typ, die Veränderlichkeit, die Serialisierbarkeit oder die Thread-Sicherheit der zurückgegebenen Liste. Wenn mehr Kontrolle über die zurückgegebene Liste erforderlich ist, verwenden Sie toCollection (Lieferant).

Wenn wir also eine bestimmte Implementierung benötigen, ArrayListkönnen wir sie beispielsweise so erhalten:

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

Java 8 (nicht modifizierbare Listen)

Wir können die Collections::unmodifiableListMethode verwenden und die in den vorherigen Beispielen zurückgegebene Liste umbrechen. Wir können auch unsere eigene benutzerdefinierte Methode schreiben als:

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);
        }
}

Und dann benutze es als:

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

Eine andere Möglichkeit besteht darin, eine collectingAndThenMethode zu verwenden, mit der eine endgültige Transformation durchgeführt werden kann, bevor das Ergebnis zurückgegeben wird:

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

Ein zu beachtender Punkt ist, dass die Methode Collections::unmodifiableListeine nicht änderbare Ansicht der angegebenen Liste gemäß Dokument zurückgibt . Eine nicht modifizierbare Ansichtssammlung ist eine Sammlung, die nicht modifizierbar ist und auch eine Ansicht auf eine Hintergrundsammlung darstellt. Beachten Sie, dass Änderungen an der Hintergrundsammlung möglicherweise weiterhin möglich sind. Wenn sie auftreten, sind sie in der nicht veränderbaren Ansicht sichtbar. Die Collector-Methode Collectors.unmodifiableListgibt jedoch eine wirklich unveränderliche Liste in Java 10 zurück .

akhil_mittal
quelle
Ich habe dies verwendet, um a Set<Double>in a umzuwandeln List<Double, wobei die Menge von LinkedHashMapder .keySet()Methode von a stammt. Eclipse sagte mir, dass es eine Typinkongruenz gab und dass ich nicht von Objectzu konvertieren konnte List<Double>. Können Sie mir sagen, warum dies passiert sein könnte? Ich habe es durch Casting umgangen, aber ich habe mich gefragt, warum es passiert.
Ungeheuer
1
Ja, da Java-Entwickler immer mehr Java 8-Funktionen verwenden sollten, ist diese Antwort besser als die beiden oben genannten Antworten.
Shubham Pandey
13

Versuchen Sie dies für Set :

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

Versuchen Sie dies für Map :

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());
Prabhakar Manthena
quelle
2

Wenn Sie Guava verwenden, importieren Sie die newArrayListMethode statisch aus der Lists- Klasse:

List<String> l = newArrayList(setOfAuthors);
Andrejs
quelle
0

Ich bin mir nicht sicher, was Sie genau über den Kontext Ihres Codes tun, aber ...

Warum überhaupt die listOfTopicAuthorsVariable machen ?

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

Das "...." steht jedoch dafür, dass Ihr Set ins Spiel gekommen ist, unabhängig davon, ob es neu ist oder von einem anderen Ort stammt.

jp093121
quelle