2010-06-17 36 views
513

Tôi muốn chuyển đổi một mảng thành một bộ trong Java. Có một số cách rõ ràng để làm điều này (tức là với một vòng lặp) nhưng tôi muốn một cái gì đó một chút neater, một cái gì đó như:Cách chuyển đổi một mảng thành một bộ trong Java

java.util.Arrays.asList(Object[] a); 

Bất kỳ ý tưởng?

Trả lời

906

Như thế này:

Set<T> mySet = new HashSet<T>(Arrays.asList(someArray)); 
+10

Tôi sẽ để lại cuối cùng, nếu không thì tốt đẹp oneliner! – despot

+3

điều này rất cao. Tại sao tạo một danh sách để lặp lại nó để tạo ra một bộ? Chỉ cần lặp lại chính mảng đó. – dataoz

+145

@dataoz: Sai; 'Arrays.asList' là O (1). – SLaks

17

Sau khi bạn làm Arrays.asList(array) bạn có thể thực hiện Set set = new HashSet(list);

Dưới đây là một phương pháp lấy mẫu, bạn có thể viết:

public <T> Set<T> GetSetFromArray(T[] array) { 
    return new HashSet<T>(Arrays.asList(array)); 
} 
+0

Tôi đã hy vọng một phương thức trả về một tập hợp trực tiếp từ một mảng, có tồn tại không? – Peter

+1

Bạn có thể viết của riêng bạn, nếu bạn đang rất háo hức :) –

-2

new HashSet<Object>(Arrays.asList(Object[] a));

Nhưng tôi nghĩ rằng điều này sẽ hiệu quả hơn:

final Set s = new HashSet<Object>();  
for (Object o : a) { s.add(o); }   
+0

Điều đó sẽ không thực sự hiệu quả hơn (ít nhất là không đáng để suy nghĩ). – ColinD

+3

Với phiên bản hàm dựng, dung lượng ban đầu của 'HashSet' được thiết lập dựa trên kích thước của mảng, ví dụ. – ColinD

+3

câu trả lời này không phải là quá câm như nó có vẻ: 'Collections.addAll (mySet, myArray);' từ java.util.Collections sử dụng cùng một trình lặp nhưng cộng với một phép toán boolean. Thêm vào đó, Bert F đã chỉ ra Collections.addAll "có khả năng chạy nhanh hơn đáng kể trong hầu hết các triển khai" hơn c.addAll (Arrays.asList (elements)) – Zorb

109

Với Guava bạn có thể làm:

T[] array = ... 
Set<T> set = Sets.newHashSet(array); 
+23

cũng là ImmutableSet.copyOf (mảng). (Tôi cũng muốn chỉ ra, tôi đoán vậy.) –

+0

Để biết danh sách cố định các phần tử bạn có thể sử dụng: ImmutableSet.of (e1, e2, ..., vi).Lưu ý rằng bạn sẽ không thể thay đổi Set sau khi tạo. – pisaruk

+0

Được cảnh báo, Guava javadoc nói: "Phương pháp này không thực sự hữu ích và có thể sẽ không còn được dùng nữa trong tương lai." Chúng hướng tới tiêu chuẩn 'mới HashSet (Arrays.asList (someArray))'. Xem https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Sets.html#newHashSet (E ...) –

166
Set<T> mySet = new HashSet<T>(); 
Collections.addAll(mySet, myArray); 

Đó là Collections.addAll(java.util.Collection, T...) từ JDK 6.

Ngoài ra: gì nếu mảng của chúng tôi là đầy đủ của nguyên thủy?

Đối với JDK < 8, tôi chỉ viết vòng lặp rõ ràng for để thực hiện thao tác quấn và thêm để đặt trong một lần truyền.

Đối với JDK> = 8, một lựa chọn hấp dẫn là một cái gì đó như:

Arrays.stream(intArray).boxed().collect(Collectors.toSet()); 
+5

Bạn có thể làm điều đó với 'java.util .Collections.addAll'. Plus, tôi sẽ không khuyên bạn nên Commons Bộ sưu tập nữa, những gì với nó không được generified và Guava hiện có. – ColinD

+13

+1 cho hiệu quả hơn câu trả lời của SLaks, mặc dù nó không phải là một lớp lót. – Adrian

+1

@Adrian Tôi đặt câu hỏi đó. Tôi nghĩ 'addAll' sẽ là O (_n_). –

6

Nhanh chóng: bạn có thể làm:

// Fixed-size list 
List list = Arrays.asList(array); 

// Growable list 
list = new LinkedList(Arrays.asList(array)); 

// Duplicate elements are discarded 
Set set = new HashSet(Arrays.asList(array)); 

và để đảo ngược

// Create an array containing the elements in a list 
Object[] objectArray = list.toArray(); 
MyClass[] array = (MyClass[])list.toArray(new MyClass[list.size()]); 

// Create an array containing the elements in a set 
objectArray = set.toArray(); 
array = (MyClass[])set.toArray(new MyClass[set.size()]); 
+0

câu trả lời toàn diện nhất! – davidgale

0

Đôi khi sử dụng một số thư viện chuẩn giúp rất nhiều. Hãy thử xem Apache Commons Collections. Trong trường hợp này vấn đề của bạn chỉ đơn giản là chuyển thành một cái gì đó như thế này

String[] keys = {"blah", "blahblah"} 
Set<String> myEmptySet = new HashSet<String>(); 
CollectionUtils.addAll(pythonKeywordSet, keys); 

Và đây là CollectionsUtils javadoc

+4

người dùng có thể không sử dụng apache commons – Adrian

+0

nếu người dùng không sử dụng apache commons, thì đó là sai lầm đầu tiên của mình. –

+3

tại sao bạn sẽ sử dụng nó thay vì 'java.util.Collections.addAll (myEmptySet, keys);' ?? – djeikyb

10

trong Eclipse Collections, sau đây sẽ làm việc:

Set<Integer> set1 = Sets.mutable.of(1, 2, 3, 4, 5); 
Set<Integer> set2 = Sets.mutable.of(new Integer[]{1, 2, 3, 4, 5}); 
MutableSet<Integer> mutableSet = Sets.mutable.of(1, 2, 3, 4, 5); 
ImmutableSet<Integer> immutableSet = Sets.immutable.of(1, 2, 3, 4, 5); 

Set<Integer> unmodifiableSet = Sets.mutable.of(1, 2, 3, 4, 5).asUnmodifiable(); 
Set<Integer> synchronizedSet = Sets.mutable.of(1, 2, 3, 4, 5).asSynchronized(); 
ImmutableSet<Integer> immutableSet = Sets.mutable.of(1, 2, 3, 4, 5).toImmutable(); 

Lưu ý: Tôi là một người có duyên cho Bộ sưu tập Eclipse

51

Java 8:

String[] strArray = {"eins", "zwei", "drei", "vier"}; 

Set<String> strSet = Arrays.stream(strArray).collect(Collectors.toSet()); 
System.out.println(strSet); 
// [eins, vier, zwei, drei] 
+0

Có đáng làm điều này song song không? –

+0

@RaffiKhatchadourian Điều này không nhất thiết phải được thực hiện song song. Arrays.stream không thực hiện bất kỳ lời hứa nào trên luồng. Bạn sẽ phải gọi song song() trên luồng kết quả cho điều đó. –

+0

Bạn cũng có thể gọi parallelStream(). Để trả lời câu hỏi của RaffiKhatchadourian, có lẽ không. Hãy thử đo nếu bạn nhận thấy bất kỳ vấn đề hiệu suất nào. –

15

Trong Java 8, chúng tôi cũng có tùy chọn sử dụng Stream.Chúng tôi có thể nhận được dòng theo những cách khác nhau:

Set<String> set = Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new)); 
System.out.println(set); 

String[] stringArray = {"A", "B", "C", "D"}; 
Set<String> strSet1 = Arrays.stream(stringArray).collect(Collectors.toSet()); 
System.out.println(strSet1); 

Set<String> strSet2 = Arrays.stream(stringArray).collect(Collectors.toCollection(HashSet::new)); 
System.out.println(strSet2); 

Mã nguồn của Collectors.toSet() cho thấy rằng yếu tố được thêm vào từng người một để một HashSet nhưng đặc điểm kỹ thuật không đảm bảo nó sẽ là một HashSet: "Không có bảo đảm theo loại , mutability, serializability, hoặc thread-safety của Set đã trả về. " Vì vậy, tốt hơn là sử dụng tùy chọn sau. Đầu ra là: [A, B, C, D] [A, B, C, D] [A, B, C, D]

+1

+1 cho 'Stream.of()' - Tôi không biết điều đó. Một câu hỏi nhỏ về 'Collectors.toSet()': bạn nói spec không đảm bảo thêm từng phần tử, nhưng đó là ý nghĩa của nó bằng cách: "tích lũy ... thành một' Bộ 'mới. Và đó là dễ đọc hơn - vì vậy thích hợp hơn cho tâm trí của tôi, nếu bạn không cần sự bảo đảm về loại bê tông, khả năng biến đổi, khả năng tuần tự và an toàn luồng. –

+0

@AndrewSpencer Spec không đảm bảo rằng việc triển khai cài đặt sẽ là 'HashSet'. Nó chỉ đảm bảo rằng nó sẽ là một 'Set' và đó là những gì tôi có ý nghĩa. Hy vọng tôi đã làm rõ nó. –

+0

Xin lỗi, và cảm ơn, tôi đã hiểu sai ý nghĩa của nó là "thông số kỹ thuật không đảm bảo được thêm một" thay vì "thông số kỹ thuật không đảm bảo một HashSet". Đề xuất chỉnh sửa để làm rõ. –

18

Biến cũng sẽ hoạt động!

Stream.of(T... values).collect(Collectors.toSet()); 
+0

cách tốt hơn là 2-3 lót. – zencv

-3
Set<T> b = new HashSet<>(Arrays.asList(requiredArray)); 
+0

Bạn trả lời khác với khía cạnh nào so với việc triển khai @SLaks đã cung cấp ít nhất 6 năm trước? http://stackoverflow.com/a/3064447 – Ferrybig

+0

câu trả lời trùng lặp ... – thanga

4

Tôi đã viết dưới đây từ những lời khuyên ở trên - ăn cắp nó ... nó đẹp!

/** 
* Handy conversion to set 
*/ 
public class SetUtil { 
    /** 
    * Convert some items to a set 
    * @param items items 
    * @param <T> works on any type 
    * @return a hash set of the input items 
    */ 
    public static <T> Set<T> asSet(T ... items) { 
     return Stream.of(items).collect(Collectors.toSet()); 
    } 
} 
+0

Mảng. luồng có thể tốt hơn Stream.of cho phần trên. –

0
private Map<Integer, Set<Integer>> nobreaks = new HashMap(); 
    nobreaks.put(1, new HashSet(Arrays.asList(new int[]{2, 4, 5}))); 
    System.out.println("expected size is 3: " +nobreaks.get(1).size()); 

đầu ra là

expected size is 3: 1 

thay đổi nó để

nobreaks.put(1, new HashSet(Arrays.asList(2, 4, 5))); 

đầu ra là

expected size is 3: 3 
-2
Set<String> set = org.mapstruct.ap.internal.util.Collections.asSet("one", "two"); 
+0

Không có chức năng như vậy. – SLaks

+0

Xin lỗi, tôi quên thêm gói –

+0

Tại sao bạn đề xuất một lớp học không có giấy tờ nội bộ? – SLaks

Các vấn đề liên quan