Самый простой способ конвертировать список в набор в Java


628

Что это самый простой способ , чтобы преобразовать Listк Setв Java?

Ответы:


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

3
Несмотря на правильность этого ответа, ему не хватает достаточного технического контекста, чтобы гарантировать, что он является наилучшим / принятым ответом, потому что здесь есть подводные камни в зависимости от того, какие реализации Setи Mapкакой используется; HashSetкак предполагается , здесь.
Madbreaks

145

Я согласен с sepp2k, но есть некоторые другие детали, которые могут иметь значение:

new HashSet<Foo>(myList);

даст вам несортированный набор, который не имеет дубликатов. В этом случае дублирование идентифицируется с помощью метода .equals () на ваших объектах. Это делается в сочетании с методом .hashCode (). (Подробнее о равенстве смотрите здесь )

Альтернатива, которая дает отсортированный набор:

new TreeSet<Foo>(myList);

Это работает, если Foo реализует Comparable. Если это не так, вы можете использовать компаратор:

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

Это зависит либо от CompareTo () (из сопоставимого интерфейса), либо от Compare () (от компаратора) для обеспечения уникальности. Итак, если вы просто заботитесь об уникальности, используйте HashSet. Если вы после сортировки, то рассмотрите TreeSet. (Помните: оптимизируйте позже!) Если эффективность времени имеет значение, используйте HashSet, если эффективность пространства имеет значение, посмотрите на TreeSet. Обратите внимание, что более эффективные реализации Set и Map доступны через Trove (и другие места).


Спасибо за включенный пользовательский вариант использования Comparator!
Джастин Папес,

70

Если вы используете библиотеку Guava :

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

или лучше:

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

2
Чем лучше ImmutableSet.copyOf?
user672009

1
Какие преимущества у newHashSet () в Guava по сравнению с базовым Java HashSet ()?
Nelda.techspiress

@ Nelda.techspiress The для документирования ОБСУЖДАЕТ когда должен или не должен быть использован метод. Обратите внимание на заключительную часть: этот метод не очень полезен и, скорее всего, в будущем будет устаревшим. Хотя я немного удивлен, что последовательность не упоминается как фактор, как ImmutableSet.of(), например, с этим. РЕДАКТИРОВАТЬ: это не может быть фактором, потому что все перегрузки не нужны.
шмосел

1
Эй, спасибо за ссылку @shmosel, но я больше искал эмпирических знаний. Для тех, кто использовал Гуаву, почему Гуава должна быть выбрана вместо HashSet?
Nelda.techspiress

27

Используя Java 8 вы можете использовать поток:

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

10
Вы проверили снижение производительности на этом? это сделало бы итератор + итератор, новый HashSet (), а затем для каждого элемента списка вызов addAll () для нового набора. В целом, ок. 5 объектов, созданных для чего-то простого, такого как новый HashSet (список).
Агостон Хорват

1
@AgostonHorvath Спасибо за ваш комментарий. Первоначально я искал эту информацию, когда пришел сюда.
TheRealChx101

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

или полный пример

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 за полный пример кода. Еще одно замечание: хэширование не всегда будет одинаковым при запуске. Это означает, что список, напечатанный после «Set values ​​.....», может быть «ABC» один прогон и «CBA» другой прогон. Как я уже упоминал в своем ответе, вы можете использовать набор деревьев, чтобы получить стабильный порядок. Другой вариант - использовать LinkedHashSet, который запоминает порядок добавления элементов в него.
Спина

8

Я бы выполнил проверку Null перед преобразованием в set.

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

3
ИлиSet<Foo> foo = myList == null ? Collections.emptySet() : new HashSet<Foo>(myList);
vegemite4me

6

Вы можете конвертировать List<>вSet<>

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

Я думаю, что вы имели в виду приведение его из списка в сет.
Саймон

6

Для Java 8 это очень просто:

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

«Настоящая» Java 8 будет использоваться new ArrayList<>();-)
JR

6

Java - addAll

set.addAll(aList);

Java - новый объект

new HashSet(list)

Java-8

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

Используя Guva

 Sets.newHashSet(list)

Apache Commons

CollectionUtils.addAll(targetSet, sourceList);

Java 10

var set = Set.copyOf(list);

5

Давайте не будем забывать нашего относительно нового друга, потоковое API. Если вам нужно предварительно обработать список перед преобразованием его в набор, лучше иметь что-то вроде:

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

4

Лучший способ использовать конструктор

Set s= new HashSet(list);

В Java 8 вы также можете использовать поток API:

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

3

Есть несколько способов получить Setкак:

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

Когда мы используем Collectors.toSet()это возвращает набор и в соответствии с доком: There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned. Если мы хотим получить, HashSetтогда мы можем использовать другую альтернативу, чтобы получить набор (чек set3).


3

С Java 10 теперь вы можете Set#copyOfлегко преобразовать его List<E>в неизменяемое Set<E>:

Пример:

var set = Set.copyOf(list);

Имейте в виду, что это неупорядоченная операция, и nullэлементы не разрешены, так какNullPointerException .

Если вы хотите, чтобы он был изменяемым, просто передайте его в конструктор Setреализации.



2

Если вы используете Eclipse Collections :

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

MutableSetИнтерфейс расширяет в java.util.Setто время как MutableIntSetинтерфейс не делает. Вы также можете преобразовать любого Iterableк Setиспользуя Setsкласс фабрики.

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

Более подробное объяснение изменчивых фабрик доступно в коллекциях Eclipse здесь .

Если вы хотите ImmutableSetот a List, вы можете использовать Setsфабрику следующим образом:

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

Примечание: я являюсь коммиттером для коллекций Eclipse


0

Помните, что преобразование из List в Set удалит дубликаты из коллекции, потому что List поддерживает дубликаты, но Set не поддерживает дубликаты в Java.

Прямое преобразование: самый распространенный и простой способ преобразования списка в набор.

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

Коллекции Apache Commons: Вы также можете использовать API Коллекции Commons для преобразования Списка в Набор: -

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

Использование потока: Другой способ - преобразовать данный список в поток, а затем установить поток: -

// 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()); 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.