Cách dễ nhất để chuyển đổi Danh sách thành Tập hợp trong Java


628

Cách dễ nhất để chuyển đổi a Listthành a Settrong Java là gì?

Câu trả lời:


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

3
Mặc dù câu trả lời đúng này thiếu bối cảnh kỹ thuật đủ để đảm bảo là câu trả lời tốt nhất / được chấp nhận, bởi vì có những cạm bẫy ở đây tùy thuộc vào việc triển khai SetMapsử dụng cái nào; HashSetđược giả định ở đây.
Madbreaks

145

Tôi đồng ý với sepp2k, nhưng có một số chi tiết khác có thể quan trọng:

new HashSet<Foo>(myList);

sẽ cung cấp cho bạn một bộ chưa sắp xếp mà không có bản sao. Trong trường hợp này, sao chép được xác định bằng phương thức .equals () trên các đối tượng của bạn. Điều này được thực hiện kết hợp với phương thức .hashCode (). (Để biết thêm về bình đẳng xem tại đây )

Một thay thế cung cấp một bộ sắp xếp là:

new TreeSet<Foo>(myList);

Điều này hoạt động nếu Foo thực hiện so sánh. Nếu không, bạn có thể muốn sử dụng một bộ so sánh:

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

Điều này phụ thuộc vào so sánh () (từ giao diện so sánh) hoặc so sánh () (từ bộ so sánh) để đảm bảo tính duy nhất. Vì vậy, nếu bạn chỉ quan tâm đến tính độc đáo, hãy sử dụng Hashset. Nếu bạn sau khi sắp xếp, hãy xem xét TreeSet. (Hãy nhớ: Tối ưu hóa sau!) Nếu vấn đề hiệu quả về thời gian sử dụng Hashset nếu hiệu quả không gian có vấn đề, hãy nhìn vào TreeSet. Lưu ý rằng việc triển khai Set và Map hiệu quả hơn có sẵn thông qua Trove (và các vị trí khác).


Cảm ơn đã bao gồm các trường hợp sử dụng so sánh tùy chỉnh!
Justin Papez

70

Nếu bạn sử dụng thư viện Guava :

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

hoặc tốt hơn:

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

2
Tại sao ImmutableSet.copyOf tốt hơn?
dùng672009

1
NewHashset () của Guava có những lợi thế gì so với Hashset () cơ bản của java?
Nelda.techspiress

@ Nelda.techspiress javadoc thảo luận khi phương thức nên hay không nên sử dụng. Lưu ý phần cuối cùng: phương pháp này không hữu ích lắm và có thể sẽ bị từ chối trong tương lai. Mặc dù tôi hơi ngạc nhiên khi tính nhất quán không được đề cập như một yếu tố, ImmutableSet.of()ví dụ như với nó . EDIT: nó có thể không phải là yếu tố vì tất cả các quá tải là không cần thiết.
shmosel

1
Xin cảm ơn đã tham khảo @shmosel, nhưng tôi đã tìm kiếm thêm kiến ​​thức thực nghiệm. Đối với những người đã sử dụng Guava, tại sao Guava sẽ được chọn hơn Hashset?
Nelda.techspiress

27

Sử dụng java 8 bạn có thể sử dụng luồng:

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

10
Bạn đã kiểm tra hình phạt hiệu suất về điều này? điều này sẽ thực hiện một iterable + iterator, một Hashset () mới, và sau đó cho mỗi mục danh sách, một lệnh gọi ALLAll () trên tập mới. Nhìn chung, cca. 5 đối tượng được tạo cho một cái gì đó đơn giản như một Hashset (danh sách) mới.
Agoston Horvath

1
@AgostonHorvath Cảm ơn bạn đã bình luận. Ban đầu tôi đã tìm kiếm thông tin đó khi tôi đến đây.
TheRealChx101

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

hoặc ví dụ hoàn chỉnh

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 cho một ví dụ mã hoàn chỉnh. Một lưu ý nữa ở đây là băm không được đảm bảo giống nhau từ chạy đến chạy. Điều đó có nghĩa là danh sách được in sau 'Đặt giá trị .....' có thể là 'ABC' một lần chạy và 'CBA' một lần chạy khác. Như tôi đã đề cập trong câu trả lời của mình, bạn có thể sử dụng một bộ cây để có được thứ tự ổn định. Một tùy chọn khác là sử dụng LinkedHashset để ghi nhớ thứ tự các mục được thêm vào nó.
Spina

8

Tôi sẽ thực hiện kiểm tra Null trước khi chuyển đổi thành thiết lập.

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

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

6

Bạn có thể chuyển đổi List<>sangSet<>

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

Tôi nghĩ bạn có nghĩa là chuyển nó từ List sang Set.
Simon

6

Đối với Java 8, nó rất dễ dàng:

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

Java 8 "thực" sẽ được sử dụng new ArrayList<>();-)
JR

6

Java - add ALL

set.addAll(aList);

Java - Đối tượng mới

new HashSet(list)

Java-8

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

Sử dụng Guva

 Sets.newHashSet(list)

Cộng đồng Apache

CollectionUtils.addAll(targetSet, sourceList);

Java 10

var set = Set.copyOf(list);

5

Chúng ta đừng quên người bạn tương đối mới của chúng ta, API luồng. Nếu bạn cần xử lý trước danh sách trước khi chuyển đổi nó thành một tập hợp, tốt hơn là có một cái gì đó như:

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

4

Cách tốt nhất để sử dụng constructor

Set s= new HashSet(list);

Trong java 8, bạn cũng có thể sử dụng luồng api ::

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

3

Có nhiều cách khác nhau để có được Setnhư:

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

Khi chúng tôi sử dụng, Collectors.toSet()nó trả về một tập hợp và theo tài liệu : There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned. Nếu chúng ta muốn lấy HashSetthì chúng ta có thể sử dụng phương án khác để lấy một bộ (kiểm tra set3).


3

Với Java 10, giờ đây bạn có thể sử dụng Set#copyOfđể dễ dàng chuyển đổi List<E>thành không thể thay đổi Set<E>:

Thí dụ:

var set = Set.copyOf(list);

Hãy nhớ rằng đây là một hoạt động không có thứ tự và nullcác yếu tố không được phép, vì nó sẽ ném một NullPointerException.

Nếu bạn muốn nó có thể sửa đổi, thì chỉ cần chuyển nó vào hàm tạo Set.


2

Một giải pháp linh hoạt hơn Java 8 với Optional.ofNullable

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

2

Nếu bạn sử dụng Bộ sưu tập Eclipse :

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

Các MutableSetgiao diện mở rộng java.util.Settrong khi MutableIntSetgiao diện thì không. Bạn cũng có thể chuyển đổi bất kỳ Iterablesang Setsử dụng Setslớp nhà máy.

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

Có nhiều lời giải thích về các nhà máy có thể thay đổi có sẵn trong Bộ sưu tập Eclipse ở đây .

Nếu bạn muốn một ImmutableSettừ a List, bạn có thể sử dụng Setsnhà máy như sau:

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

Lưu ý: Tôi là người đi làm cho Bộ sưu tập Eclipse


0

Hãy nhớ rằng, chuyển đổi từ List sang Set sẽ xóa các bản sao khỏi bộ sưu tập vì List hỗ trợ các bản sao nhưng Set không hỗ trợ các bản sao trong Java.

Chuyển đổi trực tiếp: Cách phổ biến và đơn giản nhất để chuyển đổi Danh sách thành Tập hợp

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

Bộ sưu tập Commons của Apache: Bạn cũng có thể sử dụng API Bộ sưu tập Commons để chuyển đổi Danh sách thành Tập hợp: -

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

Sử dụng Luồng: Một cách khác là chuyển đổi danh sách đã cho thành luồng, sau đó truyền phát thành:

// 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()); 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.