So konvertieren Sie ein Array in ein Set in Java

717

Ich möchte ein Array in ein Set in Java konvertieren. Es gibt einige offensichtliche Möglichkeiten, dies zu tun (dh mit einer Schleife), aber ich möchte etwas etwas ordentlicheres, etwas wie:

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

Irgendwelche Ideen?

Bob Gilmore
quelle

Antworten:

1227

So was:

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

Wenn in Java 9+ die nicht veränderbare Menge in Ordnung ist:

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

In Java 10+ kann der generische Typparameter aus dem Array-Komponententyp abgeleitet werden:

var mySet = Set.of(someArray);
SLaks
quelle
10
Ich würde den letzten <T> weglassen, sonst schöner Oneliner!
Despot
165
@dataoz: Falsch; Arrays.asListist O (1).
SLaks
67
Beachten Sie, dass bei Verwendung dieser Methode für ein Array von Grundelementen wie int [] eine Liste <int []> zurückgegeben wird. Verwenden Sie daher Wrapper-Klassen, um das beabsichtigte Verhalten zu erhalten.
T. Markle
6
@ AjayGautam: Das ist nur in Guave.
SLaks
10
Ich werde (fast) jedes Mal Lesbarkeit über Effizienz nehmen: blog.codinghorror.com/…
David Carboni
221
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);

Das ist Collections.addAll (java.util.Collection, T ...) aus JDK 6.

Zusätzlich: Was ist, wenn unser Array voller Grundelemente ist?

Für JDK <8 würde ich nur die offensichtliche forSchleife schreiben , um den Wrap und das Add-to-Set in einem Durchgang durchzuführen.

Für JDK> = 8 ist eine attraktive Option wie folgt:

Arrays.stream(intArray).boxed().collect(Collectors.toSet());
JavadocMD
quelle
5
Das kannst du machen mit java.util.Collections.addAll. Außerdem würde ich Commons Collections nicht mehr empfehlen, da es nicht generiert wird und Guava existiert.
ColinD
14
+1 für mehr Effizienz als die Antwort von SLaks, obwohl es kein Einzeiler ist.
Adrian
1
@ Adrian Ich frage das. Ich denke addAllwird O ( n ) sein.
Steve Powell
1
Ich glaube, Adrian ging es darum, wie die Lösung von SLaks eine List-Instanz erstellt, die letztendlich verworfen wird. Die tatsächlichen Auswirkungen dieser Differenz ist wahrscheinlich äußerst minimal, aber könnten von dem Kontext ab , in dem Sie tun dies - enge Schleifen oder sehr große Mengen könnten sehr unterschiedlich zwischen diesen beiden Optionen verhalten.
JavadocMD
13
Laut Collections.addAll () javadoc (Java 6): "Das Verhalten dieser Convenience-Methode ist identisch mit dem von c.addAll (Arrays.asList (elements)), aber diese Methode wird unter den meisten Implementierungen wahrscheinlich erheblich schneller ausgeführt. ""
Bert F
124

Mit Guava können Sie Folgendes tun:

T[] array = ...
Set<T> set = Sets.newHashSet(array);
ColinD
quelle
27
auch ImmutableSet.copyOf (Array). (Ich möchte auch darauf hinweisen, denke ich.)
Kevin Bourrillion
Für eine feste Liste von Elementen können Sie Folgendes verwenden: ImmutableSet.of (e1, e2, ..., en). Beachten Sie, dass Sie dieses Set nach seiner Erstellung nicht mehr ändern können.
Pisaruk
1
Seien Sie gewarnt, der Guava Javadoc sagt: "Diese Methode ist eigentlich nicht sehr nützlich und wird wahrscheinlich in Zukunft veraltet sein." Sie weisen auf den Standard hin new HashSet<T>(Arrays.asList(someArray)). Siehe 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]
max
quelle
2
Lohnt es sich, dies parallel zu tun?
Raffi Khatchadourian
@RaffiKhatchadourian Dies wird nicht unbedingt parallel durchgeführt. Arrays.stream macht keine Versprechungen im Stream. Dazu müssten Sie parallel () für den resultierenden Stream aufrufen.
Felix S
Sie können auch parallelStream () aufrufen. Um die Frage von @ RaffiKhatchadourian zu beantworten, wahrscheinlich nicht. Versuchen Sie zu messen, wenn Sie Leistungsprobleme bemerken.
Randy the Dev
6
Vermeiden Sie im Allgemeinen Parallelen. Standardmäßig wird ein einzelner Threadpool für Ihre Anwendung verwendet, und der Aufwand für das Starten von Threads und das Verknüpfen ist geringer als das sequentielle Streaming durch Hunderte von Elementen. Nur in sehr wenigen Situationen bringt Parallel tatsächlich Nutzen.
Tkruse
45

Varargs wird auch funktionieren!

Stream.of(T... values).collect(Collectors.toSet());
Alex
quelle
2
viel besser als 2-3 Liner.
Senseiwu
30

Java 8

Wir haben die Möglichkeit, Streamauch zu verwenden. Wir können Streams auf verschiedene Arten erhalten:

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

Der Quellcode von Collectors.toSet()zeigt, dass Elemente HashSeteinzeln zu einem hinzugefügt werden , die Spezifikation jedoch nicht garantiert, dass es sich um ein Element handelt HashSet.

"Es gibt keine Garantie für den Typ, die Veränderlichkeit, die Serialisierbarkeit oder die Thread-Sicherheit des zurückgegebenen Sets."

Daher ist es besser, die spätere Option zu verwenden. Die Ausgabe ist: [A, B, C, D] [A, B, C, D] [A, B, C, D]

Unveränderliches Set (Java 9)

In Java 9 wurde die Set.ofstatische Factory-Methode eingeführt, die unveränderliche Mengen für die bereitgestellten Elemente oder das Array zurückgibt.

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

Weitere Informationen finden Sie unter Statische Factory-Methoden für unveränderliche Sets .

Unveränderliches Set (Java 10)

Wir können ein unveränderliches Set auch auf zwei Arten erhalten:

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

Die Methode verwendet Collectors.toUnmodifiableList()intern die Set.ofin Java 9 eingeführte Methode . Weitere Informationen finden Sie auch in meiner Antwort .

akhil_mittal
quelle
1
+1 für Stream.of()- das wusste ich nicht. Ein kleines Problem Collectors.toSet(): Sie sagen, die Spezifikation garantiert nicht das Hinzufügen von Elementen nacheinander, aber das ist es, was es bedeutet: "sammelt sich ... in einem neuen Set". Und es ist besser lesbar - meiner Meinung nach vorzuziehen, wenn Sie nicht die Garantien für konkreten Typ, Veränderbarkeit, Serialisierbarkeit und Thread-Sicherheit benötigen.
Andrew Spencer
@AndrewSpencer Spec garantiert nicht, dass die festgelegte Implementierung erfolgt HashSet. Es garantiert nur, dass es ein sein wird Setund das meine ich. Hoffe ich habe es geklärt.
akhil_mittal
Tut mir leid, und danke, ich habe es falsch verstanden, was bedeutet, dass "spec nicht garantiert, dass eins nach dem anderen hinzugefügt wird" und nicht "spec garantiert kein HashSet". Schlug eine Änderung zur Verdeutlichung vor.
Andrew Spencer
19

Nachdem Sie dies getan haben Arrays.asList(array), können Sie ausführenSet set = new HashSet(list);

Hier ist eine Beispielmethode, die Sie schreiben können:

public <T> Set<T> GetSetFromArray(T[] array) {
    return new HashSet<T>(Arrays.asList(array));
}
Petar Minchev
quelle
Ich hatte auf eine Methode gehofft, die einen Satz direkt aus einem Array zurückgibt. Gibt es eine?
1
Sie können Ihre eigenen schreiben, wenn Sie so eifrig sind :)
Petar Minchev
12

In Eclipse-Sammlungen funktioniert Folgendes:

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

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen

Donald Raab
quelle
7

Schnell: Sie können tun:

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

und umzukehren

// 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
quelle
6

Ich habe das Folgende aus dem Rat oben geschrieben - stiehl es ... es ist schön!

/**
 * 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
quelle
Arrays.stream ist möglicherweise besser als Stream.of.
Ashley Frieze
5

Es hat schon viele gute Antworten, aber die meisten von ihnen werden nicht mit Array von Primitiven arbeiten (wie int[], long[], char[], byte[], etc.)

In Java 8 und höher können Sie das Array mit folgenden Elementen versehen:

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

Dann konvertieren, um mit Stream zu setzen:

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

Manchmal hilft die Verwendung einiger Standardbibliotheken sehr. Versuchen Sie, sich die Apache Commons-Sammlungen anzusehen . In diesem Fall werden Ihre Probleme einfach in so etwas umgewandelt

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

Und hier ist das CollectionsUtils javadoc

mnagni
quelle
4
Benutzer verwendet möglicherweise keine Apache Commons
Adrian
Wenn der Benutzer keine Apache Commons verwendet, ist dies sein erster Fehler.
Jeryl Cook
3
warum sollten Sie dies anstelle von verwenden java.util.Collections.addAll(myEmptySet, keys);?
Djeikyb
0

Verwenden Sie CollectionUtilsoder ArrayUtilsvonstanford-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
quelle
0

In Java 10 :

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

Set.copyOfGibt eine nicht modifizierbare Datei zurück, Setdie die Elemente der angegebenen enthält Collection.

 Das Gegebene Collectiondarf nicht sein nullund darf keine nullElemente enthalten .

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

die Ausgabe ist

expected size is 3: 1

ändere es auf

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

die Ausgabe ist

expected size is 3: 3
Bruce Zu
quelle
-1

Für alle, die nach Android suchen:

Kotlin-Sammlungslösung

Das Sternchen *ist der spreadOperator. Es wendet alle Elemente in einer Sammlung einzeln an, die jeweils an einen varargMethodenparameter übergeben werden. Es ist äquivalent zu:

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)

Das Übergeben keiner Parameter setOf()führt zu einem leeren Satz.

Darüber hinaus setOfkönnen Sie eine dieser Optionen auch für einen bestimmten Hash-Typ verwenden:

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

So definieren Sie den Sammlungselementtyp explizit.

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

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

Aber ich denke, das wäre effizienter:

final Set s = new HashSet<Object>();    
for (Object o : a) { s.add(o); }         
Ben S.
quelle
Das wäre nicht wirklich effizienter (zumindest nicht erwägenswert).
ColinD
3
Bei der Konstruktorversion wird die Anfangskapazität von HashSetbeispielsweise auf der Grundlage der Größe des Arrays festgelegt.
ColinD
3
Diese Antwort ist nicht so dumm, wie es scheint: 'Collections.addAll (mySet, myArray);' from java.util.Collections verwenden denselben Iterator, aber plus eine boolesche Operation. Und wie Bert F betonte, wird Collections.addAll "unter den meisten Implementierungen wahrscheinlich erheblich schneller ausgeführt" als c.addAll (Arrays.asList (Elemente))
Zorb
-4
Set<T> b = new HashSet<>(Arrays.asList(requiredArray));
Satyendra Jaiswal
quelle
1
In welchem ​​Aspekt unterscheiden Sie sich von der Implementierung, die @SLaks vor mindestens 6 Jahren bereitgestellt hat? stackoverflow.com/a/3064447
Ferrybig