A maneira mais concisa de converter um conjunto <T> em uma lista <T>

201

Por exemplo, atualmente estou fazendo isso:

Set<String> setOfTopicAuthors = ....

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

Você pode vencer isso?

Jacques René Mesrine
fonte
2
Utilização java.util.Collection: O (0)
Tim
@Carl, tenho que enviar o conjunto para uma interface de terceiros que exija uma lista. @ Tim Gostaria de poder alterar a interface de terceiros para usar o Collection.
Jacques René Mesrine
1
Entendo; Exceto quaisquer restrições estranhas, eu aceitaria a resposta de Roger. No entanto, a menos que você realmente use a Lista novamente, eu ignoraria atribuí-la a qualquer coisa (por exemplo, use foo.api (nova ArrayList <String> (listOfTopicAuthors)) em vez de foo.api (lista)).
2424 Carl
2
@ JacquesRenéMesrine: A primeira linha de código em questão é enganosa: Esperado: Set<String> setOfTopicAuthors = ....Real:Set<String> listOfTopicAuthors = ....
realPK
Ou poderia ser uma maneira alternativa de fazer o mesmo List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new)), detalhada na resposta vinculada.
Naman

Respostas:

432
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
fonte
1
... desafiando radicalmente as convenções de código Java: oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus
depois disso, quando tentei acessar o elemento da lista, ele me deu erro ", java.lang.ClassCastException: java.lang.Integer não pode ser convertido para java.lang.String" ..don; não sei por que ... é simples list.get (int) é isso ... alguma sugestão?
CoDe
2
Eu acredito em Java 7 e acima, você pode omitir o parâmetro type para ArrayListproduzir: List<String> l = new ArrayList<>(listOfTopicAuthors); Mais conciso sem usar uma biblioteca externa?
Brett Duncavage 30/10
Ele lançará NullPointerException caso listOfTopicAuthorsseja nulo.
precisa saber é
91
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Adamski
fonte
4
por responder no mesmo minuto da resposta aceita e não receber o crédito. 1
jayeffkay 4/15
@Adamski Acabo com uma lista cujo índice começa em 1 em vez de 0, algum remédio?
Jack
1
@ Jack: Isso definitivamente não será o caso. No Javadoc de java.util.List: "Listas (como matrizes Java) são baseadas em zero."
23916 Adamski
@Adamski Obrigado pela resposta. Eu sei que as listas devem ser e são baseadas em zero, e é por isso que isso é tão estranho para mim. Depois de converter meu conjunto em uma lista, não consigo executar nenhuma operação iterativa para foreach, sort, etc. Recebo uma NullPointerException, no entanto, quando espero que minha lista nenhum dos elementos seja nulo, e o único estranho que noto é que o índice começa em 1. No entanto, se eu apenas criar uma lista normal, o índice começa em 0. Estranho?
Jack
1
@Jack: Isso parece muito estranho. Se você postar seu código como uma pergunta separada, tenho certeza de que alguém poderá ajudá-lo.
Adamski 22/02
23

Considerando que temos Set<String> stringSet, podemos usar o seguinte:

Java 10 (lista não modificável)

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

Java 8 (listas modificáveis)

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

De acordo com o documento para o métodotoList()

Não há garantias sobre o tipo, mutabilidade, serialização ou segurança de thread da Lista retornada; se for necessário mais controle sobre a lista retornada, use toCollection (Supplier).

Portanto, se precisarmos de uma implementação específica, por exemplo ArrayList, podemos obtê-lo desta maneira:

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

Java 8 (listas não modificáveis)

Podemos fazer uso do Collections::unmodifiableListmétodo e agrupar a lista retornada nos exemplos anteriores. Também podemos escrever nosso próprio método personalizado como:

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 depois use-o como:

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

Outra possibilidade é fazer uso de um collectingAndThenmétodo que permita alguma transformação final antes de retornar o resultado:

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

Um ponto a ser observado é que o método Collections::unmodifiableListretorna uma visão inalterável da lista especificada, conforme o documento . Uma coleção de visualizações não modificáveis ​​é uma coleção que não pode ser modificada e também é uma visualização em uma coleção de suporte. Observe que as alterações na coleção de backup ainda podem ser possíveis e, se ocorrerem, serão visíveis na visualização inalterável. Mas o método coletor Collectors.unmodifiableListretorna uma lista verdadeiramente imutável no Java 10 .

akhil_mittal
fonte
Eu usei isso para converter um Set<Double>a um List<Double, onde o conjunto veio de um LinkedHashMap's .keySet()método. O Eclipse me disse que havia uma incompatibilidade de tipo e que não podia converter de Objectpara List<Double>. Você poderia me dizer por que isso pode ter acontecido? Eu consegui contornar isso lançando, mas estava me perguntando por que isso acontece.
Ungeheuer
1
Sim, como os desenvolvedores Java devem usar cada vez mais recursos do Java 8, essa resposta é melhor que as 2 respostas acima.
Shubham Pandey
13

Tente isto para Set :

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

Tente isto para o mapa :

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
fonte
2

Se você estiver usando o Guava, importe estaticamente o newArrayListmétodo da classe Lists :

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

não tenho certeza do que você está fazendo exatamente através do contexto do seu código, mas ...

por que fazer a listOfTopicAuthorsvariável?

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

o "...." representa como seu conjunto entrou em jogo, seja novo ou proveniente de outro local.

jp093121
fonte