A maneira mais fácil de converter uma lista em um conjunto em Java


628

Qual é a maneira mais fácil de converter um Listpara um Setem Java?

Respostas:


1065
Set<Foo> foo = new HashSet<Foo>(myList);

3
Embora correta, essa resposta carece de contexto técnico suficiente para garantir a melhor / aceita resposta, porque existem armadilhas aqui, dependendo de quais implementações Sete qual Mapdelas está sendo usada; HashSeté assumido aqui.
21418 Madbreaks

145

Concordo com o sepp2k, mas existem outros detalhes que podem ser importantes:

new HashSet<Foo>(myList);

fornecerá um conjunto não classificado que não possui duplicatas. Nesse caso, a duplicação é identificada usando o método .equals () em seus objetos. Isso é feito em combinação com o método .hashCode (). (Para mais informações sobre igualdade, veja aqui )

Uma alternativa que fornece um conjunto classificado é:

new TreeSet<Foo>(myList);

Isso funciona se o Foo implementa Comparable. Caso contrário, convém usar um comparador:

Set<Foo> lSet = new TreeSet<Foo>(someComparator);
lSet.addAll(myList);

Isso depende de compareTo () (da interface comparável) ou compare () (do comparador) para garantir a exclusividade. Portanto, se você se preocupa apenas com a exclusividade, use o HashSet. Se você estiver após a classificação, considere o TreeSet. (Lembre-se: otimizar mais tarde!) Se a eficiência do tempo interessar, use um HashSet se a eficiência do espaço importar, consulte o TreeSet. Observe que implementações mais eficientes de Set e Map estão disponíveis no Trove (e em outros locais).


Obrigado por incluir o caso de uso do Comparator personalizado!
Justin Papez 24/09

70

Se você usa a biblioteca Guava :

Set<Foo> set = Sets.newHashSet(list);

ou melhor:

Set<Foo> set = ImmutableSet.copyOf(list);

2
Por que ImmutableSet.copyOf é melhor?
user672009

1
Que vantagens o newHashSet () do Guava tem sobre o novo java básico HashSet ()?
Nelda.techspiress

@ Nelda.techspiress O javadoc discute quando o método deve ou não ser usado. Observe a parte final: esse método não é muito útil e provavelmente será preterido no futuro. Embora eu esteja um pouco surpreso, a consistência não é mencionada como um fator, como acontece com ImmutableSet.of(), por exemplo. EDIT: pode não ser um fator, porque todas as sobrecargas são desnecessárias.
Shmosel

1
Ei, obrigado pela referência @shmosel, mas eu estava procurando mais por conhecimento empírico. Para aqueles que usaram o Goiaba, por que o Goiaba seria escolhido sobre o HashSet?
Nelda.techspiress

27

Usando o java 8, você pode usar o stream:

List<Integer> mylist = Arrays.asList(100, 101, 102);
Set<Integer> myset = mylist.stream().collect(Collectors.toSet()));

10
Você verificou a penalidade de desempenho nisso? isso faria um iterável + iterador, um novo HashSet () e, para cada item da lista, uma chamada addAll () no novo conjunto. No geral, cca. 5 objetos criados para algo tão simples quanto um novo HashSet (lista).
Agoston Horvath

1
@AgostonHorvath Obrigado pelo seu comentário. Eu estava originalmente procurando essas informações quando cheguei aqui.
TheRealChx101

17
Set<E> alphaSet  = new HashSet<E>(<your List>);

ou exemplo completo

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ListToSet
{
    public static void main(String[] args)
    {
        List<String> alphaList = new ArrayList<String>();
        alphaList.add("A");
        alphaList.add("B");
        alphaList.add("C");
        alphaList.add("A");
        alphaList.add("B");
        System.out.println("List values .....");
        for (String alpha : alphaList)
        {
            System.out.println(alpha);
        }
        Set<String> alphaSet = new HashSet<String>(alphaList);
        System.out.println("\nSet values .....");
        for (String alpha : alphaSet)
        {
            System.out.println(alpha);
        }
    }
}

1
+1 para um exemplo de código completo. Uma observação adicional aqui é que não é garantido que o hash seja o mesmo de execução para execução. Isso significa que a lista impressa após 'Definir valores ...' pode ser 'ABC' uma execução e 'CBA' outra execução. Como mencionei na minha resposta, você pode usar um conjunto de árvores para obter uma ordem estável. Outra opção seria usar um LinkedHashSet que lembre a ordem em que os itens foram adicionados a ele.
Spina

8

Eu faria uma verificação nula antes de converter para definir.

if(myList != null){
Set<Foo> foo = new HashSet<Foo>(myList);
}

3
OuSet<Foo> foo = myList == null ? Collections.emptySet() : new HashSet<Foo>(myList);
vegemite4me

6

Você pode converter List<>paraSet<>

Set<T> set=new HashSet<T>();

//Added dependency -> If list is null then it will throw NullPointerExcetion.

Set<T> set;
if(list != null){
    set = new HashSet<T>(list);
}

Eu acho que você quis dizer transmiti-lo da lista para o conjunto.
Simon

6

Para Java 8 é muito fácil:

List < UserEntity > vList= new ArrayList<>(); 
vList= service(...);
Set<UserEntity> vSet= vList.stream().collect(Collectors.toSet());

Java 8 "real" seria usar new ArrayList<>();-)
JR

6

Java - addAll

set.addAll(aList);

Java - novo Objeto

new HashSet(list)

Java-8

list.stream().collect(Collectors.toSet());

Usando o Guva

 Sets.newHashSet(list)

Apache Commons

CollectionUtils.addAll(targetSet, sourceList);

Java 10

var set = Set.copyOf(list);

5

Não vamos esquecer nosso amigo relativamente novo, API de fluxo. Se você precisar pré-processar a lista antes de convertê-la em um conjunto, é melhor ter algo como:

list.stream().<here goes some preprocessing>.collect(Collectors.toSet());

4

A melhor maneira de usar o construtor

Set s= new HashSet(list);

No java 8, você também pode usar a API do stream:

Set s= list.stream().collect(Collectors.toSet());

3

Existem várias maneiras de obter um Setcomo:

    List<Integer> sourceList = new ArrayList();
    sourceList.add(1);
    sourceList.add(2);
    sourceList.add(3);
    sourceList.add(4);

    // Using Core Java
    Set<Integer> set1 = new HashSet<>(sourceList);  //needs null-check if sourceList can be null.

    // Java 8
    Set<Integer> set2 = sourceList.stream().collect(Collectors.toSet());
    Set<Integer> set3 = sourceList.stream().collect(Collectors.toCollection(HashSet::new));

    //Guava
    Set<Integer> set4 = Sets.newHashSet(sourceList);

    // Apache commons
    Set<Integer> set5 = new HashSet<>(4);
    CollectionUtils.addAll(set5, sourceList);

Quando usamos Collectors.toSet()ele retorna um conjunto e de acordo com o doc: There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned. Se quisermos obter um HashSet, podemos usar a outra alternativa para obter um conjunto (verificação set3).


3

Com o Java 10, agora você pode usar Set#copyOfpara converter facilmente um List<E>em um não modificável Set<E>:

Exemplo:

var set = Set.copyOf(list);

Lembre-se de que esta é uma operação não ordenada e que nullelementos não são permitidos, pois isso gera a NullPointerException.

Se você deseja que seja modificável, basta passá-lo ao construtor uma Setimplementação.


2

Uma solução mais resistente ao Java 8 com Optional.ofNullable

Set<Foo> mySet = Optional.ofNullable(myList).map(HashSet::new).orElse(null);

2

Se você usar o Eclipse Collections :

MutableSet<Integer> mSet = Lists.mutable.with(1, 2, 3).toSet();
MutableIntSet mIntSet = IntLists.mutable.with(1, 2, 3).toSet();

A MutableSetinterface se estende java.util.Setenquanto a MutableIntSetinterface não. Você também pode converter qualquer Iterableum em Setusando a Setsclasse de fábrica.

Set<Integer> set = Sets.mutable.withAll(List.of(1, 2, 3));

Há mais explicações sobre as fábricas mutáveis ​​disponíveis nas Coleções Eclipse aqui .

Se você deseja um ImmutableSetde a List, pode usar a Setsfábrica da seguinte maneira:

ImmutableSet<Integer> immutableSet = Sets.immutable.withAll(List.of(1, 2, 3))

Nota: Eu sou um confirmador das Coleções Eclipse


0

Lembre-se de que a conversão de Lista em Conjunto removerá duplicatas da coleção, pois a Lista suporta duplicatas, mas o Conjunto não suporta duplicatas em Java.

Conversão direta: a maneira mais comum e simples de converter uma lista em um conjunto

// Creating a list of strings
List<String> list = Arrays.asList("One", "Two", "Three", "Four");

// Converting a list to set
Set<String> set = new HashSet<>(list);

Coleções do Apache Commons: Você também pode usar a API do Commons Collections para converter uma lista em um conjunto: -

// Creating a list of strings
List<String> list = Arrays.asList("One", "Two", "Three", "Four");

// Creating a set with the same number of members in the list 
Set<String> set = new HashSet<>(4);

// Adds all of the elements in the list to the target set
CollectionUtils.addAll(set, list);

Usando Stream: Outra maneira é converter a lista fornecida em stream e depois transmitir para definir: -

// Creating a list of strings 
List<String> list = Arrays.asList("One", "Two", "Three", "Four"); 

// Converting to set using stream 
Set<String> set = list.stream().collect(Collectors.toSet()); 
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.