Najbardziej zwięzły sposób na konwersję zestawu <T> na listę <T>

201

Na przykład obecnie robię to:

Set<String> setOfTopicAuthors = ....

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

Czy potrafisz to pokonać?

Jacques René Mesrine
źródło
2
Użyj java.util.Collection: O (0)
Tim
@Carl, muszę przesłać zestaw do interfejsu innej firmy, który wymaga listy. @Tim Chciałbym móc zmienić interfejs innej firmy, aby korzystać z kolekcji.
Jacques René Mesrine
1
Widzę; pomijając wszelkie dziwne ograniczenia, wybrałbym odpowiedź Rogera. Chociaż, chyba że użyjesz ponownie Listy, pomiń przypisywanie jej do czegokolwiek (tj. Użyj foo.api (nowa ArrayList <String> (listOfTopicAuthors)) zamiast foo.api (lista)).
Carl
2
@ JacquesRenéMesrine: Pierwszy wiersz omawianego kodu wprowadza w błąd: oczekiwany: Set<String> setOfTopicAuthors = ....rzeczywisty:Set<String> listOfTopicAuthors = ....
realPK
Alternatywnym sposobem na zrobienie tego samego może być List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))opisany w powiązanej odpowiedzi.
Naman

Odpowiedzi:

432
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
źródło
1
... a tym samym radykalnie przeciwstawiając się konwencjom kodu Java: oracle.com/technetwork/java/javase/documentation/... ! :) :)
Håvard Geithus
po tym, gdy próbowałem uzyskać dostęp do elementu listy, pojawia się błąd: „java.lang.ClassCastException: java.lang.Integer nie można rzutować na java.lang.String” ..don; t wiedzieć, dlaczego… to jest prosta lista.get (int) to wszystko ... jakieś sugestie?
CoDe,
2
Wierzę, że w Javie 7 i nowszych można pominąć parametr type, aby uzyskać ArrayList: List<String> l = new ArrayList<>(listOfTopicAuthors); Najbardziej zwięzły bez korzystania z zewnętrznej biblioteki?
Brett Duncavage
Zgłasza wyjątek NullPointerException w przypadku, gdy listOfTopicAuthorsma wartość NULL.
w35l3y 30.08.16
91
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Adamski
źródło
4
za udzielenie odpowiedzi w tej samej minucie, co odpowiedź zaakceptowana i nie otrzymanie kredytu. +1
jayeffkay,
@Adamski Skończyłem z listą, której indeks zaczyna się od 1 zamiast 0, jakieś lekarstwo?
Jack
1
@Jack: Z pewnością tak nie będzie. Z Javadoc z java.util.List: „Listy (takie jak tablice Java) są oparte na zerach”.
Adamski
@Adamski Dzięki za odpowiedź. Wiem, że listy powinny być oparte na zerach i dlatego jest to dla mnie takie dziwne. Po przekonwertowaniu mojego zestawu na listę nie mogę wykonać żadnej iteracyjnej operacji na nim foreach, sortować itp. Dostaję wyjątek NullPointerException, jednak gdy oczekuję, że moja lista nie ma żadnych elementów, a jedyne dziwne jest to, że indeks zaczyna się od 1. Jednak jeśli utworzę zwykłą listę, indeks zaczyna się od 0. Dziwne?
Jack
1
@Jack: Brzmi bardzo dziwnie. Jeśli opublikujesz swój kod jako osobne pytanie, jestem pewien, że ktoś będzie w stanie Ci pomóc.
Adamski
23

Biorąc pod uwagę, że mamy, Set<String> stringSetmożemy użyć następujących elementów:

Java 10 (lista niemodyfikowalna)

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

Java 8 (Listy modyfikowalne)

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

Zgodnie z dokumentem dla metodytoList()

Nie ma żadnych gwarancji dotyczących rodzaju, zmienności, serializacji lub bezpieczeństwa wątków zwracanej listy; jeśli wymagana jest większa kontrola nad zwróconą listą, użyj funkcji toCollection (dostawca).

Jeśli więc potrzebujemy konkretnej implementacji, np. ArrayListMożemy ją uzyskać w ten sposób:

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

Java 8 (Listy niemodyfikowalne)

Możemy skorzystać z Collections::unmodifiableListmetody i zawinąć listę zwróconą w poprzednich przykładach. Możemy również napisać własną metodę niestandardową jako:

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

A następnie użyj go jako:

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

Inną możliwością jest użycie collectingAndThenmetody, która pozwala na dokonanie ostatecznej transformacji przed zwróceniem wyniku:

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

Jeden punkt, aby pamiętać, jest to, że metoda Collections::unmodifiableListzwraca niemodyfikowalne widok podanej listy, jak na doc . Kolekcja niemodyfikowalna jest kolekcją niemodyfikowalną, a także widokiem na kolekcję podkładową. Należy pamiętać, że zmiany w kolekcji kopii zapasowych mogą być nadal możliwe, a jeśli wystąpią, są widoczne w widoku niemodyfikowalnym. Ale metoda kolektora Collectors.unmodifiableListzwraca naprawdę niezmienną listę w Javie 10 .

akhil_mittal
źródło
Użyłem tego, aby przekonwertować a Set<Double>na List<Double, gdzie zestaw pochodzi z metody LinkedHashMapa .keySet(). Eclipse powiedział mi, że wystąpiło niedopasowanie typu i że nie mogę przekonwertować z Objectna List<Double>. Czy możesz mi powiedzieć, dlaczego tak się stało? Obejrzałem to, rzucając, ale zastanawiałem się, dlaczego tak się dzieje.
Ungeheuer
1
Tak, ponieważ programiści Java powinni używać coraz więcej funkcji Java 8, ta odpowiedź jest lepsza niż powyższe 2 odpowiedzi.
Shubham Pandey,
13

Wypróbuj to dla zestawu :

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

Wypróbuj to dla mapy :

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
źródło
2

Jeśli używasz Guava, statycznie importujesz newArrayListmetodę z klasy Lists :

List<String> l = newArrayList(setOfAuthors);
Andrejs
źródło
0

nie jestem pewien, co dokładnie robisz w kontekście kodu, ale ...

po listOfTopicAuthorsco w ogóle tworzyć zmienną?

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

„....” reprezentuje jednak zestaw, który wszedł do gry, bez względu na to, czy jest nowy, czy pochodzi z innej lokalizacji.

jp093121
źródło