Найпростіший спосіб перетворення списку в набір на Java


627

Який найпростіший спосіб перетворити в Listна SetJava?

Відповіді:


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 реалізує порівнянне. Якщо це не так, ви можете скористатися компаратором:

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

Це залежить або від сравнениеTo () (від порівнянного інтерфейсу), або порівняння () (від компаратора), щоб забезпечити унікальність. Отже, якщо ви просто піклуєтеся про унікальність, використовуйте HashSet. Якщо ви після сортування, то розгляньте TreeSet. (Пам’ятайте: Оптимізуйте пізніше!) Якщо питання щодо ефективності часу використовують HashSet, якщо важлива космічна ефективність, подивіться на TreeSet. Зауважте, що більш ефективні реалізації Set і Map доступні через Trove (та інші місця).


Дякуємо за включений у користувальницький випадок використання компаратор!
Джастін Папес

70

Якщо ви використовуєте бібліотеку Guava :

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

або, ще краще:

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

2
Чому ImmutableSet.copyOf краще?
користувач672009

1
Які переваги має новий HashSet () Guava перед базовим Java-новим HashSet ()?
Nelda.techspiress

@ Nelda.techspiress The для документування ОБГОВОРЮЄ коли повинен чи не повинен бути використаний метод. Зауважте підсумкову частину: цей метод не дуже корисний і, швидше за все, буде застарілим у майбутньому. Хоча я трохи здивований, консистенція не згадується як фактор, як це ImmutableSet.of(), наприклад. EDIT: це може не бути фактором, оскільки всі перевантаження зайві.
шмосель

1
Ей, дякую за посилання @shmosel, але я більше шукав емпіричних знань. Для тих, хто використовував Guava, чому саме Guava обрали б HashSet?
Nelda.techspiress

27

За допомогою Java 8 ви можете використовувати stream:

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

10
Ви перевірили покарання за це? це зробить ітерабельний + ітератор, новий HashSet (), а потім для кожного елемента списку виклик addAll () у новому наборі. Загалом, cca. 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 для повного прикладу коду. Однією з додаткових приміток є те, що хешування не гарантовано буде однаковим від запуску до запуску. Це означає, що список, надрукований після "Встановити значення .....", може бути "ABC" одного запуску та "CBA" іншого запуску. Як я вже згадував у своїй відповіді, ви можете використовувати набір дерев, щоб отримати стабільне впорядкування. Іншим варіантом було б використання LinkedHashSet, який запам'ятовує порядок додавання до нього елементів.
Шпина

8

Я б здійснив перевірку Null перед перетворенням у встановлений.

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

Використання Гуви

 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 ви також можете використовувати stream 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()він повертає набір і відповідно до doc : 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

Більш стійке рішення для Java 8 Optional.ofNullable

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

2

Якщо ви використовуєте Eclipse Collection :

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 не підтримує дублікатів у 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 Collections для перетворення списку в набір: -

// 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.