Cara mengonversi Array ke Set di Java

717

Saya ingin mengonversi array ke Set di Java. Ada beberapa cara yang jelas untuk melakukan ini (yaitu dengan loop) tetapi saya ingin sesuatu yang sedikit lebih rapi, seperti:

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

Ada ide?

Bob Gilmore
sumber

Jawaban:

1227

Seperti ini:

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

Di Java 9+, jika set yang tidak dapat dimodifikasi ok:

Set<T> mySet = Set.of(someArray);

Dalam Java 10+, parameter tipe generik dapat disimpulkan dari tipe komponen array:

var mySet = Set.of(someArray);
Slaks
sumber
10
Saya akan meninggalkan <T> terakhir, jika tidak ada penumpang yang baik!
despot
165
@dataoz: Salah; Arrays.asListadalah O (1).
SLaks
67
Perhatikan bahwa jika Anda menggunakan metode ini pada array primitif seperti int [] itu akan mengembalikan Daftar <int []> jadi Anda harus menggunakan kelas wrapper untuk mendapatkan perilaku yang dimaksud.
T. Markle
6
@AjayGautam: Itu hanya di Jambu.
SLaks
10
Saya akan mengambil keterbacaan atas efisiensi (hampir) setiap kali: blog.codinghorror.com/…
David Carboni
221
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);

Itu adalah Collections.addAll (java.util.Collection, T ...) dari JDK 6.

Selain itu: bagaimana jika array kami penuh dengan primitif?

Untuk JDK <8, saya hanya akan menulis forloop yang jelas untuk melakukan wrap dan add-to-set dalam satu pass.

Untuk JDK> = 8, opsi yang menarik adalah sesuatu seperti:

Arrays.stream(intArray).boxed().collect(Collectors.toSet());
JavadocMD
sumber
5
Anda bisa melakukannya dengan java.util.Collections.addAll. Plus, saya tidak akan merekomendasikan Commons Collections lagi, apa yang tidak dibuat dan Guava ada
ColinD
14
+1 karena lebih efisien daripada jawaban SLaks, meskipun itu bukan satu baris.
Adrian
1
@Adrian saya mempertanyakan itu. Saya pikir addAllakan menjadi O ( n ).
Steve Powell
1
Saya percaya poin Adrian adalah tentang bagaimana solusi SLaks menciptakan contoh instance yang akhirnya dibuang. Dampak aktual dari perbedaan itu mungkin sangat minimal, tetapi bisa tergantung pada konteks di mana Anda melakukan ini - loop ketat atau set yang sangat besar mungkin berperilaku sangat berbeda antara kedua opsi ini.
JavadocMD
13
Per the Collections.addAll () javadoc (Java 6): "Perilaku metode kenyamanan ini identik dengan perilaku c.addAll (Arrays.asList (elemen)), tetapi metode ini cenderung berjalan secara signifikan lebih cepat di sebagian besar implementasi. "
Bert F
124

Dengan Jambu Biji, Anda bisa melakukannya:

T[] array = ...
Set<T> set = Sets.newHashSet(array);
ColinD
sumber
27
juga ImmutableSet.copyOf (array). (Saya ingin menunjukkan juga, saya kira.)
Kevin Bourrillion
Untuk daftar elemen tetap yang bisa Anda gunakan: ImmutableSet.of (e1, e2, ..., en). Perhatikan Anda tidak akan dapat mengubah Set ini setelah dibuat.
pisaruk
1
Berhati-hatilah, javadoc Guava mengatakan: "Metode ini sebenarnya tidak terlalu berguna dan kemungkinan akan usang di masa depan." Mereka menunjuk ke arah standar new HashSet<T>(Arrays.asList(someArray)). Lihat google.github.io/guava/releases/19.0/api/docs/com/google/common/…
Alexander Klimetschek
67

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]
maks
sumber
2
Apakah pantas melakukan ini secara paralel?
Raffi Khatchadourian
@RaffiKhatchadourian Ini belum tentu dilakukan secara paralel. Arrays.stream tidak membuat janji apa pun di arus. Anda harus memanggil parallel () pada stream yang dihasilkan untuk itu.
Felix S
Anda juga dapat memanggil parallelStream (). Untuk menjawab pertanyaan @ RaffiKhatchadourian, mungkin tidak. Coba ukur jika Anda melihat ada masalah kinerja.
Randy the Dev
6
Secara umum, hindari paralel. Secara default menggunakan threadpool tunggal di aplikasi Anda, dan overhead untuk memulai utas dan bergabung lebih buruk daripada streaming berurutan melalui ratusan item. Hanya dalam beberapa situasi yang paralel benar-benar membawa manfaat.
tkruse
45

Varargs akan bekerja juga!

Stream.of(T... values).collect(Collectors.toSet());
Alex
sumber
2
cara yang lebih baik bahwa 2-3 liner.
senseiwu
30

Java 8

Kami memiliki opsi untuk menggunakan Streamjuga. Kita bisa mendapatkan streaming dengan berbagai cara:

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

// if you need HashSet then use below option.
Set<String> strSet2 = Arrays.stream(stringArray).collect(Collectors.toCollection(HashSet::new));
System.out.println(strSet2);

Kode sumber Collectors.toSet()menunjukkan bahwa elemen ditambahkan satu per satu ke HashSettetapi spesifikasi tidak menjamin itu akan menjadi HashSet.

"Tidak ada jaminan pada jenis, mutabilitas, serializability, atau keamanan ulir dari Set yang dikembalikan."

Jadi lebih baik menggunakan opsi nanti. Outputnya adalah: [A, B, C, D] [A, B, C, D] [A, B, C, D]

Set Abadi (Java 9)

Java 9 memperkenalkan Set.ofmetode pabrik statis yang mengembalikan set tetap untuk elemen yang disediakan atau array.

@SafeVarargs
static <E> Set<E> of​(E... elements)

Periksa Metode Pabrik Statis Tidak Berubah untuk detailnya.

Set Abadi (Java 10)

Kita juga bisa mendapatkan perangkat permanen dengan dua cara:

  1. Set.copyOf(Arrays.asList(array))
  2. Arrays.stream(array).collect(Collectors.toUnmodifiableList());

Metode ini secara Collectors.toUnmodifiableList()internal menggunakan Set.ofdiperkenalkan di Jawa 9. Juga periksa jawaban saya ini untuk lebih.

akhil_mittal
sumber
1
+1 untuk Stream.of()- Saya tidak tahu itu. Sebuah pertengkaran kecil tentang Collectors.toSet(): Anda mengatakan spec tidak menjamin penambahan elemen satu per satu, tapi itulah artinya dengan: "mengakumulasi ... menjadi yang baru Set". Dan itu lebih mudah dibaca - jadi lebih disukai bagi saya, jika Anda tidak memerlukan jaminan jenis konkret, mutabilitas, serializability dan keamanan thread.
Andrew Spencer
@AndrewSpencer Spec tidak menjamin bahwa implementasi yang ditetapkan akan HashSet. Itu hanya menjamin bahwa itu akan menjadi Setdan itu yang saya maksud. Semoga saya klarifikasi.
akhil_mittal
Maaf, dan terima kasih, saya salah membaca sebagai arti "spec tidak menjamin ditambahkan satu per satu" daripada "spec tidak menjamin HashSet". Usulkan hasil edit untuk menjelaskan.
Andrew Spencer
19

Setelah Anda melakukannya, Arrays.asList(array)Anda dapat menjalankanSet set = new HashSet(list);

Berikut adalah contoh metode, Anda dapat menulis:

public <T> Set<T> GetSetFromArray(T[] array) {
    return new HashSet<T>(Arrays.asList(array));
}
Petar Minchev
sumber
Saya berharap untuk metode yang mengembalikan set langsung dari array, apakah ada?
1
Anda dapat menulis sendiri, jika Anda sangat ingin :)
Petar Minchev
12

Di Eclipse Collections , yang berikut ini akan berfungsi:

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

Catatan: Saya pengendara untuk Eclipse Collections

Donald Raab
sumber
7

Dengan cepat: Anda dapat melakukan:

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

dan untuk membalikkan

// 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()]);
Pierre-Olivier Pignon
sumber
6

Saya telah menulis di bawah ini dari saran di atas - mencurinya ... itu bagus!

/**
 * 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());
    }
}
Ashley Frieze
sumber
Arrays.stream mungkin lebih baik daripada Stream.of untuk yang di atas.
Ashley Frieze
5

Telah ada banyak jawaban yang besar sudah, tapi kebanyakan dari mereka tidak akan bekerja dengan array primitif (seperti int[], long[], char[], byte[], dll)

Di Java 8 dan di atas, Anda bisa mengotak array dengan:

Integer[] boxedArr = Arrays.stream(arr).boxed().toArray(Integer[]::new);

Kemudian konversi untuk diatur menggunakan aliran:

Stream.of(boxedArr).collect(Collectors.toSet());
Julia
sumber
0

Kadang menggunakan beberapa perpustakaan standar banyak membantu. Cobalah untuk melihat Koleksi Apache Commons . Dalam hal ini masalah Anda hanya ditransformasikan menjadi sesuatu seperti ini

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

Dan di sini adalah javadoc CollectionsUtils

mnagni
sumber
4
pengguna mungkin tidak menggunakan apache commons
Adrian
jika pengguna tidak menggunakan apache commons, maka itu adalah kesalahan pertamanya.
Jeryl Cook
3
mengapa Anda menggunakan ini bukan java.util.Collections.addAll(myEmptySet, keys);??
djeikyb
0

Gunakan CollectionUtilsatau ArrayUtilsdaristanford-postagger-3.0.jar

import static edu.stanford.nlp.util.ArrayUtils.asSet;
or 
import static edu.stanford.nlp.util.CollectionUtils.asSet;

  ...
String [] array = {"1", "q"};
Set<String> trackIds = asSet(array);
Olexandra Dmytrenko
sumber
0

Di Jawa 10 :

String[] strs = {"A", "B"};
Set<String> set = Set.copyOf(Arrays.asList(strs));

Set.copyOfmengembalikan yang tidak dapat dimodifikasi yang Setmengandung unsur-unsur yang diberikan Collection.

 Yang diberikan Collectiontidak boleh null, dan tidak boleh mengandung nullelemen apa pun .

Oleksandr Pyrohov
sumber
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());

outputnya adalah

expected size is 3: 1

ubah ke

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

outputnya adalah

expected size is 3: 3
Bruce Zu
sumber
-1

Bagi siapa pun yang memecahkan untuk Android:

Solusi Koleksi Kotlin

Tanda bintang *adalah spreadoperator. Itu berlaku semua elemen dalam koleksi secara individual, masing-masing diteruskan untuk varargparameter metode. Itu sama dengan:

val myArray = arrayOf("data", "foo")
val mySet = setOf(*myArray)

// Equivalent to
val mySet = setOf("data", "foo")

// Multiple spreads ["data", "foo", "bar", "data", "foo"]
val mySet = setOf(*myArray, "bar", *myArray)

Melewati tanpa parameter setOf()menghasilkan set kosong.

Selain itu setOf, Anda juga dapat menggunakan semua ini untuk jenis hash tertentu:

hashSetOf()
linkedSetOf()
mutableSetOf()
sortableSetOf()

Ini adalah cara mendefinisikan jenis item koleksi secara eksplisit.

setOf<String>()
hashSetOf<MyClass>()
Gibolt
sumber
-2

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

Tapi saya pikir ini akan lebih efisien:

final Set s = new HashSet<Object>();    
for (Object o : a) { s.add(o); }         
Ben S
sumber
Itu tidak akan benar-benar lebih efisien (setidaknya tidak layak untuk dipikirkan).
ColinD
3
Dengan versi konstruktor, kapasitas awal HashSetdiatur berdasarkan ukuran array, misalnya.
ColinD
3
jawaban ini tidak sebodoh kelihatannya: 'Collections.addAll (mySet, myArray);' dari java.util.Collections menggunakan iterator yang sama tetapi ditambah satu operasi boolean. Ditambah seperti yang ditunjukkan oleh Bert F Collections.addAll "kemungkinan akan berjalan lebih cepat secara signifikan di bawah sebagian besar implementasi" daripada c.addAll (Arrays.asList (elemen))
Zorb
-4
Set<T> b = new HashSet<>(Arrays.asList(requiredArray));
Satyendra Jaiswal
sumber
1
Dalam aspek apa Anda menjawab berbeda dari implementasi yang telah disediakan @SLaks setidaknya 6 tahun yang lalu? stackoverflow.com/a/3064447
Ferrybig