821

I would like to convert an array to a Set in Java. There are some obvious ways of doing this (i.e. with a loop) but I would like something a bit neater, something like:

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

Any ideas?

Bob Gilmore
  • 12,608
  • 13
  • 46
  • 53

19 Answers19

1388

Like this:

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

In Java 9+, if unmodifiable set is ok:

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

In Java 10+, the generic type parameter can be inferred from the arrays component type:

var mySet = Set.of(someArray);

Be careful

Set.of throws IllegalArgumentException - if there are any duplicate elements in someArray. See more details: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Set.html#of(E...)

Jackkobec
  • 5,889
  • 34
  • 34
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 11
    I would leave out the last , otherwise nice oneliner! – despot Jul 06 '11 at 10:06
  • 3
    @SLaks Exactly. asList just creates a view on top of the array. – Jagat Jun 25 '12 at 13:12
  • 1
    @SLaks I exaggerated a bit. But you still create 1 more object than if you iterated over the array yourself or used the helper method provided by Collections, as indicated by JavadocMD below. That is unless I am missing something obvious. – dataoz Jul 12 '12 at 19:33
  • 89
    Note that if you use this method on an array of primitives such as int[] it will return a List so you should use wrapper classes to get the intended behavior. – T. Markle Sep 22 '12 at 04:53
  • 1
    Actually, if you put the code in a method with a generic return type , attempting to pass a primitive array as T[] won't compile, so no problem. Otherwise, one would need to check someArray.getClass().getComponentType().isPrimitive(). – PNS Mar 04 '13 at 18:41
  • 3
    Sets.newHashSet is a cleaner solution – Ajay Gautam Oct 02 '13 at 19:01
  • 6
    @AjayGautam: That's only in Guava. – SLaks Oct 02 '13 at 19:15
  • 10
    I'll take readability over efficiency (nearly) every time: http://blog.codinghorror.com/hardware-is-cheap-programmers-are-expensive/ – David Carboni Apr 21 '15 at 14:29
  • @yegor256 The valid explicit syntax is `Arrays.asList()`. But it is better to rely on type inference whenever possible. – Nayuki Mar 01 '16 at 02:37
  • 1
    Set set = Collections.asSet("one", "two"); – Oleg Cherednik Aug 01 '17 at 15:19
  • 1
    There is a major difference between using new HashSet(Arrays.asList(someArray)); and Set.of(someArray); that is, former produces a Non-Immutable collection while later produce an immutable collection. – Damith Jul 30 '18 at 04:24
  • 2
    I observed that new HashSet(Arrays.asList(someArray)); would not add each element separately , it just adds the whole array as set's first item . – Vikash Kumar Jan 04 '19 at 18:46
  • The time complexities of all of these solutions are O(n), correct? I assume there is no faster way to do it. – John Farkerson Oct 26 '19 at 09:19
  • @SLaks - how would I convert an array of primitive integers to a TreeSet of Integers ? – MasterJoe May 05 '20 at 05:34
  • 1
    Arrays.asList(someArray)); will not work for `int[] someArray` – ACV Jan 27 '21 at 22:20
  • 1
    `Set.of(someArray);` throws an `IllegalArgumentException` in case `someArray` has duplicate item(s) while `new HashSet<>(Arrays.asList(someArray));` would create the set successfully. – Ali Jul 12 '21 at 23:28
243
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);

That's Collections.addAll(java.util.Collection, T...) from JDK 6.

Additionally: what if our array is full of primitives?

For JDK < 8, I would just write the obvious for loop to do the wrap and add-to-set in one pass.

For JDK >= 8, an attractive option is something like:

Arrays.stream(intArray).boxed().collect(Collectors.toSet());
JavadocMD
  • 4,397
  • 2
  • 25
  • 23
  • 5
    You can do that with `java.util.Collections.addAll`. Plus, I wouldn't recommend Commons Collections anymore, what with it not being generified and Guava existing . – ColinD Jun 17 '10 at 18:40
  • 14
    +1 for being more efficient than SLaks's answer, even though it's not a one-liner. – Adrian Apr 10 '12 at 22:17
  • 1
    @Adrian I question that. I think `addAll` will be O(_n_). – Steve Powell Oct 22 '13 at 15:35
  • 1
    I believe Adrian's point was about how SLaks' solution creates a List instance which is ultimately thrown out. The actual impact of that difference is *probably* extremely minimal, but *could* depend on the context in which you're doing this -- tight loops or very large sets might behave very differently between these two options. – JavadocMD Oct 22 '13 at 19:00
  • 15
    Per the Collections.addAll() javadoc (Java 6): "The behavior of this convenience method is identical to that of c.addAll(Arrays.asList(elements)), but this method is likely to run significantly faster under most implementations." – Bert F Feb 03 '14 at 22:50
  • Interesting fact? Coding in NetBeans, I wrote my own loop to copy the array to the set. NetBeans popped up a light bulb suggesting I use `mySet.addAll(Arrays.asList(myArray));` – downeyt Jul 18 '15 at 14:02
  • 1
    @user2418306 Indeed! Of course you can't have a collection of primitives anyway, so you're going to have to wrap them. Edited with recommendations. – JavadocMD Apr 13 '16 at 23:34
  • JDK 9+ (not primitives): `Set.of(myArray)` – Andreas Apr 24 '18 at 17:45
  • This should be the real answer simply for the built in method `Collections.addAll(java.util.Collection, T...)` – Mr00Anderson Jul 20 '20 at 05:25
127

With Guava you can do:

T[] array = ...
Set<T> set = Sets.newHashSet(array);
ColinD
  • 108,630
  • 30
  • 201
  • 202
  • 28
    also ImmutableSet.copyOf(array). (I like to point out also's, I guess.) – Kevin Bourrillion Jun 17 '10 at 21:26
  • For a fixed list of elements you could use: ImmutableSet.of(e1, e2, ..., en). Notice you would not be able to change this Set after its creation. – Pikachu Aug 17 '16 at 17:02
  • 2
    Be warned, the Guava javadoc says: "This method is not actually very useful and will likely be deprecated in the future." They point towards the standard `new HashSet(Arrays.asList(someArray))`. See https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Sets.html#newHashSet(E...) – Alexander Klimetschek Nov 11 '16 at 01:51
71

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]
vega8
  • 534
  • 1
  • 5
  • 25
max
  • 781
  • 6
  • 3
  • 2
    Is it worth doing this in parallel? – Raffi Khatchadourian Jan 06 '16 at 18:10
  • @RaffiKhatchadourian This is not necessarily being done in parallel. Arrays.stream does not make any promises on the stream. You would have to call parallel() on the resulting stream for that. – Felix S Jan 20 '16 at 11:41
  • You could also call parallelStream(). To answer @RaffiKhatchadourian's question, probably not. Try measuring if you're noticing any performance issues. – Randy the Dev Dec 01 '16 at 00:14
  • 6
    Generally, avoid parallel. By default it uses a single threadpool accross your application, and the overhead to start threads and join is worse than sequentially streaming through hundreds of items. Only in very few situations does parallel actually bring benefit. – tkruse Mar 03 '17 at 08:02
50

Varargs will work too!

Stream.of(T... values).collect(Collectors.toSet());
Alex
  • 603
  • 7
  • 13
37

Java 8

We have the option of using Stream as well. We can get stream in various ways:

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

The source code of Collectors.toSet() shows that elements are added one by one to a HashSet but specification does not guarantee it will be a HashSet.

"There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned."

So it is better to use the later option. The output is: [A, B, C, D] [A, B, C, D] [A, B, C, D]

Immutable Set (Java 9)

Java 9 introduced Set.of static factory method which returns immutable set for the provided elements or the array.

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

Check Immutable Set Static Factory Methods for details.

Immutable Set (Java 10)

We can also get an immutable set in two ways:

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

The method Collectors.toUnmodifiableList() internally makes use of Set.of introduced in Java 9. Also check this answer of mine for more.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
  • 1
    +1 for `Stream.of()` - I didn't know that one. A small quibble about `Collectors.toSet()`: you say the spec does not guarantee adding elements one by one, but that's what it means by: "accumulates ... into a new `Set`". And it's more readable - so preferable to my mind, if you don't need the guarantees of concrete type, mutability, serializability and thread-safety. – Andrew Spencer Feb 19 '16 at 09:00
  • @AndrewSpencer Spec does not guarantee that the set implementation will be `HashSet`. It only guarantees that it will be a `Set` and that is what I mean. Hope I clarified it. – akhil_mittal Feb 20 '16 at 10:12
  • Sorry, and thanks, I misread it as meaning "spec does not guarantee added one by one" rather than "spec does not guarantee a HashSet". Proposed an edit to clarify. – Andrew Spencer Feb 24 '16 at 10:36
19

After you do Arrays.asList(array) you can execute Set set = new HashSet(list);

Here is a sample method, you can write:

public <T> Set<T> GetSetFromArray(T[] array) {
    return new HashSet<T>(Arrays.asList(array));
}
Petar Minchev
  • 46,889
  • 11
  • 103
  • 119
17

There has been a lot of great answers already, but most of them won't work with array of primitives (like int[], long[], char[], byte[], etc.)

In Java 8 and above, you can box the array with:

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

Then convert to set using stream:

Stream.of(boxedArr).collect(Collectors.toSet());
Kennard
  • 845
  • 2
  • 12
  • 32
12

In Eclipse Collections, the following will work:

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

Note: I am a committer for Eclipse Collections

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
7

I've written the below from the advice above - steal it... it's nice!

/**
 * 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
  • 4,993
  • 2
  • 29
  • 23
7

Quickly : you can do :

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

and to reverse

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

If you need to build an immutable set with only one element inside it, you can use Collections.singleton(...). Here is an example:

Set<String> mySet = Collections.singleton("Have a good day :-)");

This doesn't answer the original question but might be useful to someone (it would have been at least to me). If you think this answer does not fit just tell me and I will delete it.

Stypox
  • 963
  • 11
  • 18
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());

the output is

expected size is 3: 1

change it to

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

the output is

expected size is 3: 3
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Bruce Zu
  • 507
  • 6
  • 17
0

In Java 10:

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

Set.copyOf returns an unmodifiable Set containing the elements of the given Collection.

 The given Collection must not be null, and it must not contain any null elements.

Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
0

Use CollectionUtils or ArrayUtils from stanford-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

For anyone solving for Android:

Kotlin Collections Solution

The asterisk * is the spread operator. It applies all elements in a collection individually, each passed in order to a vararg method parameter. It is equivalent to:

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)

Passing no parameters setOf() results in an empty set.

In addition to setOf, you can also use any of these for a specific hash type:

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

This is how to define the collection item type explicitly.

setOf<String>()
hashSetOf<MyClass>()
Gibolt
  • 42,564
  • 15
  • 187
  • 127
0

Sometime using some standard libraries helps a lot. Try to look at the Apache Commons Collections. In this case your problems is simply transformed to something like this

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

And here is the CollectionsUtils javadoc

mnagni
  • 9
  • 1
-1

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

But I think this would be more efficient:

final Set s = new HashSet<Object>();    
for (Object o : a) { s.add(o); }         
Zorb
  • 726
  • 11
  • 24
Ben S
  • 68,394
  • 30
  • 171
  • 212
  • That wouldn't really be more efficient (at least not worth thinking about). – ColinD Jun 17 '10 at 18:46
  • 3
    With the constructor version, the initial capacity of the `HashSet` is set based on the size of the array, for instance. – ColinD Jun 17 '10 at 18:55
  • 3
    this answer is not so dumb as it seems: 'Collections.addAll(mySet, myArray);' from java.util.Collections use the same iterator but plus one boolean operation . Plus as Bert F pointed out Collections.addAll " likely to run significantly faster under most implementations" than c.addAll(Arrays.asList(elements)) – Zorb Oct 14 '15 at 22:05
-4
Set<T> b = new HashSet<>(Arrays.asList(requiredArray));
Slava Vedenin
  • 58,326
  • 13
  • 40
  • 59
  • 2
    In what aspect does you answer differ from the implementation @SLaks has provided as least 6 years ago? http://stackoverflow.com/a/3064447 – Ferrybig Jan 19 '16 at 17:16