Il modo più conciso per convertire un Set <T> in un Elenco <T>


201

Ad esempio, attualmente sto facendo questo:

Set<String> setOfTopicAuthors = ....

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

Riesci a battere questo?


2
Usa java.util.Collection: O (0)
Tim

@Carl, devo inviare il set a un'interfaccia di terze parti che richiede un elenco. @Tim Vorrei poter cambiare l'interfaccia di terze parti per utilizzare Collection.
Jacques René Mesrine,

1
Vedo; salvo strani vincoli, andrei con la risposta di Roger. Tuttavia, a meno che non utilizzi nuovamente l'Elenco, salterei assegnandolo a qualsiasi cosa (cioè, uso foo.api (new ArrayList <String> (listOfTopicAuthors)) invece di foo.api (list)).
Carl,

2
@ JacquesRenéMesrine: la prima riga di codice in questione è fuorviante: prevista: Set<String> setOfTopicAuthors = ....effettiva:Set<String> listOfTopicAuthors = ....
realPK

Oppure potrebbe essere un modo alternativo di fare lo stesso List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new)), dettagliato nella risposta collegata.
Naman,

Risposte:


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

1
... e quindi sfidando radicalmente le convenzioni del codice Java: oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus,

dopo questo quando ho provato ad accedere all'elemento dell'elenco mi ha dato l'errore, "java.lang.ClassCastException: java.lang.Integer non può essere trasmesso a java.lang.String" ..don; t so perché..è semplice list.get (int) questo è tutto ... qualche suggerimento?
CoDe

2
Credo in Java 7 e versioni successive che puoi omettere il parametro type a ArrayListcedendo: il List<String> l = new ArrayList<>(listOfTopicAuthors); più conciso senza usare una libreria esterna?
Brett Duncavage,

Genererà NullPointerException nel caso in cui listOfTopicAuthorssia null.
w35l3y,

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

4
per rispondere nello stesso minuto della risposta accettata e non ottenere il credito. +1
jayeffkay

@Adamski Finisco con un elenco il cui indice inizia da 1 invece di 0, qualche rimedio?
Jack,

1
@Jack: Sicuramente non sarà così. Dal Javadoc di java.util.List: "Gli elenchi (come gli array Java) sono basati su zero".
Adamski,

@Adamski Grazie per la risposta. So che le liste dovrebbero essere e sono basate su zero, motivo per cui questo è così strano per me. Dopo aver convertito il mio set in un elenco non riesco a eseguire alcuna operazione iterativa su di esso per ogni tipo, ordinamento, ecc. Ottengo una NullPointerException, tuttavia quando mi aspetto che il mio elenco nessuno degli elementi sia nullo, e l'unico strano che noto è che il L'indice inizia da 1. Tuttavia, se creo solo un elenco normale, l'indice inizia da 0. Strano?
Jack,

1
@Jack: sembra molto strano. Se pubblichi il tuo codice come domanda separata, sono sicuro che qualcuno sarà in grado di aiutarti.
Adamski,

23

Considerando che abbiamo Set<String> stringSetpossiamo usare quanto segue:

Java 10 (Elenco non modificabile)

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

Java 8 (Elenchi modificabili)

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

Come da documento per il metodotoList()

Non vi sono garanzie sul tipo, la mutabilità, la serializzabilità o la sicurezza dei thread dell'elenco restituito; se è necessario un maggiore controllo sull'elenco restituito, utilizzare toCollection (fornitore).

Quindi, se abbiamo bisogno di un'implementazione specifica, ad esempio ArrayList, possiamo ottenerla in questo modo:

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

Java 8 (Elenchi non modificabili)

Possiamo usare il Collections::unmodifiableListmetodo e racchiudere l'elenco restituito negli esempi precedenti. Possiamo anche scrivere il nostro metodo personalizzato come:

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

E poi usalo come:

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

Un'altra possibilità è quella di utilizzare il collectingAndThenmetodo che consente di eseguire alcune trasformazioni finali prima di restituire il risultato:

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

Un punto da notare è che il metodo Collections::unmodifiableListrestituisce una vista non modificabile dell'elenco specificato, come da documento . Una raccolta di viste non modificabile è una raccolta non modificabile ed è anche una vista su una raccolta di supporto. Si noti che le modifiche alla raccolta di backup potrebbero essere ancora possibili e, se si verificano, sono visibili attraverso la vista non modificabile. Ma il metodo collector Collectors.unmodifiableListrestituisce un elenco davvero immutabile in Java 10 .


Ho usato questo per convertire un Set<Double>ad una List<Double, in cui l'insieme è venuto da una LinkedHashMap's .keySet()metodo. Eclipse mi disse che c'era una mancata corrispondenza del tipo e che non potevo convertire da Objectin List<Double>. Potresti dirmi perché questo potrebbe essere successo? L'ho aggirato dal casting, ma mi chiedevo perché succedesse.
Ungeheuer,

1
Sì, poiché gli sviluppatori Java dovrebbero utilizzare sempre più funzionalità Java 8, questa risposta è migliore delle 2 risposte precedenti.
Shubham Pandey,

13

Prova questo per Set :

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

Prova questo per Mappa :

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

2

Se stai usando Guava, importa staticamente il newArrayListmetodo dalla classe Lists :

List<String> l = newArrayList(setOfAuthors);

0

non sono sicuro di cosa stai facendo esattamente attraverso il contesto del tuo codice ma ...

perché rendere la listOfTopicAuthorsvariabile affatto?

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

il "...." rappresenta comunque il tuo set entrato in gioco, sia esso nuovo o proveniente da un'altra posizione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.