Bir diziyi Java'da bir kümeye dönüştürme


718

Bir dizi Java bir Set dönüştürmek istiyorum. Bunu yapmanın bazı belirgin yolları vardır (yani bir döngü ile) ama biraz daha temiz bir şey istiyorum, şöyle bir şey:

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

Herhangi bir fikir?

Yanıtlar:


1229

Bunun gibi:

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

Java 9 ve sonraki sürümlerinde değiştirilemez küme tamamsa:

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

Java 10+ sürümünde, genel tür parametresi diziler bileşen türünden çıkarılabilir:

var mySet = Set.of(someArray);

10
Ben son <T>, aksi takdirde güzel oneliner bırakacaktı!
despot

165
@dataoz: Yanlış; Arrays.asListR, O (1) 'dir.
SLaks

67
Bu yöntemi int [] gibi bir ilkel dizisinde kullanırsanız, istenen davranışı elde etmek için sarmalayıcı sınıflarını kullanmanız için bir Liste <int []> döndüreceğini unutmayın.
T. Markle

6
@AjayGautam: Bu sadece Guava'da.
SLaks

10
Verimlilik (neredeyse) her seferinde okunabilirliği alacağım: blog.codinghorror.com/…
David Carboni

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

Budur Collections.addAll (java.util.Collection T ...) JDK 6 dan.

Ayrıca: dizimiz ilkellerle doluysa ne olacak?

JDK <8 için, sadece forbir geçişte sarma ve eklenti ayarlamak için bariz döngü yazacağım .

JDK> = 8 için çekici bir seçenek şuna benzer:

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

5
Bunu ile yapabilirsiniz java.util.Collections.addAll. Ayrıca, artık Commons Collections'ı tavsiye etmem, neyin üretilmediği ve Guava mevcut değil.
ColinD

14
Tek astar olmasa da SLaks'ın cevabından daha verimli olduğu için +1.
Adrian

1
@ Adrian bunu soruyorum. Bence addAllO ( n ) olacak.
Steve Powell

1
Adrian'ın amacı SLaks'ın çözümünün nihayetinde atılan bir List örneğini nasıl oluşturduğuyla ilgili olduğuna inanıyorum. Bu farkın gerçek etkisi muhtemelen çok azdır, ancak bunu yaptığınız içeriğe bağlı olabilir - sıkı döngüler veya çok büyük kümeler bu iki seçenek arasında çok farklı davranabilir.
JavadocMD

13
Collections.addAll () javadoc (Java 6) uyarınca: "Bu kolaylık yönteminin davranışı, c.addAll (Arrays.asList (elements)) ile aynıdır, ancak bu yöntem çoğu uygulamada önemli ölçüde daha hızlı çalışır. "
Bert F

124

İle Guava Yapabileceğiniz:

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

27
ayrıca ImmutableSet.copyOf (dizi). (Ben de işaret etmek istiyorum, sanırım.)
Kevin Bourrillion

Sabit bir öğe listesi için şunları kullanabilirsiniz: ImmutableSet.of (e1, e2, ..., en). Bu Set'i oluşturulduktan sonra değiştiremeyeceğinize dikkat edin.
pisaruk

1
Dikkatli olun, Guava javadoc şöyle diyor: "Bu yöntem aslında çok kullanışlı değil ve gelecekte kullanımdan kaldırılacak." Standarda işaret ediyorlar new HashSet<T>(Arrays.asList(someArray)). Bkz. Google.github.io/guava/releases/19.0/api/docs/com/google/common/…
Alexander Klimetschek

68

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]

2
Bunu paralel olarak yapmaya değer mi?
Raffi Khatchadourian

@RaffiKhatchadourian Bu mutlaka paralel olarak yapılmamaktadır. Arrays.stream akışta herhangi bir söz vermez. Bunun için elde edilen akışta parallel () yöntemini çağırmanız gerekir.
Felix S

Ayrıca parallelStream () öğesini çağırabilirsiniz. @ RaffiKhatchadourian'ın sorusuna cevap vermek için muhtemelen hayır. Herhangi bir performans sorunu fark edip etmediğinizi ölçmeyi deneyin.
Randy the Dev

6
Genel olarak paralel olmaktan kaçının. Varsayılan olarak, uygulamanızda tek bir iş parçacığı kullanır ve iş parçacıklarını başlatmak ve katılmak için ek yük, yüzlerce öğeden sırayla akış yapmaktan daha kötüdür. Sadece çok az durumda paralel aslında fayda sağlar.
tkruse

45

Varargs da çalışacak!

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

2
2-3 astar daha iyi.
senseiwu

30

Java 8

Bizim de kullanma seçeneğimiz var Stream. Çeşitli şekillerde akış elde edebiliriz:

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

Kaynak kodu, Collectors.toSet()öğelerin bire birer birer eklendiğini gösterir, HashSetancak şartname bunun olacağını garanti etmez HashSet.

"İade edilen Setin türü, değiştirilebilirliği, serileştirilebilirliği veya iş parçacığı güvenliği konusunda hiçbir garanti yoktur."

Bu yüzden sonraki seçeneği kullanmak daha iyidir. Çıktı: [A, B, C, D] [A, B, C, D] [A, B, C, D]

Değişmez Küme (Java 9)

Java 9 tanıtıldı Set.of , sağlanan öğeler veya dizi için değişmez kümeyi döndüren statik fabrika yöntemini .

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

Kontrol Ayrıntılar için Dayanıklı Set Statik Fabrika Yöntemlerini .

Değişmez Küme (Java 10)

Ayrıca iki şekilde değişmez bir set alabiliriz:

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

Yöntem Collectors.toUnmodifiableList()dahili Set.ofolarak Java 9'da kullanılmaya başlandı. Ayrıca daha fazla bilgi için bu cevabımı kontrol edin .


1
+1 için Stream.of()- Bunu bilmiyordum. Şununla ilgili küçük bir tartışma Collectors.toSet(): Spesifikasyonun öğeleri tek tek eklemeyi garanti etmediğini söylüyorsunuz, ama bunun anlamı: "yeni ... birikir Set". Ve daha okunabilir - beton türü, değişebilirlik, serileştirilebilirlik ve iplik güvenliği garantilerine ihtiyacınız yoksa, aklıma çok tercih edilir.
Andrew Spencer

@AndrewSpencer Spec, ayarlanan uygulamanın olacağını garanti etmez HashSet. Sadece bunun bir olacağını garanti Setederim. Umarım açıklığa kavuştum.
akhil_mittal

Üzgünüz, ve teşekkürler, "spec bir HashSet garanti etmez" yerine "spec tek tek eklendi garanti etmez" anlamı olarak yanlış okudum. Açıklığa kavuşturulması için bir düzenleme önerdi.
Andrew Spencer

19

Yaptıktan sonra Arrays.asList(array) sen yürütebilirsinizSet set = new HashSet(list);

İşte örnek bir yöntem, yazabilirsiniz:

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

Bir dizi doğrudan bir diziden döndüren bir yöntem için umuyordum, biri var mı?

1
Çok istekli iseniz kendi yazabilirsiniz :)
Petar Minchev

12

In Eclipse Koleksiyonları , şu işe yarar:

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

Not: Eclipse Collections için bir komisyoncuyum


7

Çabuk: şunları yapabilirsiniz:

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

ve tersine çevirmek

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

6

Yukarıdaki tavsiyeden aşağıda yazdım - çal ... güzel!

/**
 * 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());
    }
}

Arrays.stream, yukarıdaki akıştan daha iyi olabilir.
Ashley Frieze

5

Orada zaten büyük yanıtlar çok olmuştur, ama bunların çoğu ilkel dizisi ile çalışmaz (gibi int[], long[], char[], byte[], vb)

Java 8 ve üstü sürümlerde diziyi şunlarla kutulayabilirsiniz:

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

Sonra akışı kullanarak kümeye dönüştürün:

Stream.of(boxedArr).collect(Collectors.toSet());

0

Bazen bazı standart kütüphaneleri kullanmak çok yardımcı olur. Apache Commons Koleksiyonlarına bakmaya çalışın . Bu durumda sorunlarınız basitçe böyle bir şeye dönüşür

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

Ve burada KoleksiyonlarUtils javadoc


4
kullanıcı apache commons kullanamaz
Adrian

kullanıcı apache ortaklarını kullanmıyorsa, bu onun ilk hatasıdır.
Jeryl Cook

3
neden bunu java.util.Collections.addAll(myEmptySet, keys);kullanasın?
djeikyb

0

Kullanım CollectionUtilsveya ArrayUtilsgelenstanford-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);

0

In Java 10 :

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

Set.copyOfSetverilen öğeleri içeren değiştirilemez bir öğe döndürür Collection.

 Verilen Collectionolmamalı nullve herhangi bir nullunsur içermemelidir .


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

çıktı

expected size is 3: 1

olarak değiştir

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

çıktı

expected size is 3: 3

-1

Android için çözen herkes için:

Kotlin Koleksiyonlar Çözümü

Yıldız işareti *olan spreadoperatör. Bir koleksiyondaki tüm öğeleri, her biri bir varargyöntem parametresine iletilmek üzere ayrı ayrı uygular . Şuna eşdeğerdir:

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)

Hiçbir parametre iletilmezse setOf()boş bir küme oluşur.

Ayrıca setOf, bunlardan herhangi birini belirli bir karma türü için de kullanabilirsiniz:

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

Koleksiyon öğesi türünü bu şekilde açıkça tanımlayabilirsiniz.

setOf<String>()
hashSetOf<MyClass>()

-2

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

Ama bunun daha verimli olacağını düşünüyorum:

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

Bu gerçekten daha verimli olmazdı (en azından düşünmeye değmez).
ColinD

3
Yapıcı sürümünde, örneğin ilk kapasitesi HashSetdizinin boyutuna göre ayarlanır.
ColinD

3
bu cevap göründüğü kadar aptal değil: 'Collections.addAll (mySet, myArray);' Koleksiyonlar aynı yineleyiciyi ama artı bir boole işlemini kullanır. Artı Bert F c.addAll daha "büyük olasılıkla önemli ölçüde daha hızlı çoğu uygulamalarında altında çalıştırmak için" Collections.addAll dışarı (Arrays.asList (elementleri)) belirttiği gibi
Zorb

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.