[java] How to initialize HashSet values by construction?

I need to create a Set with initial values.

Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");

Is there a way to do this in one line of code? For instance, it's useful for a final static field.

This question is related to java collections constructor initialization hashset

The answer is


Collection literals were scheduled for Java 7, but didn't make it in. So nothing automatic yet.

You can use guava's Sets:

Sets.newHashSet("a", "b", "c")

Or you can use the following syntax, which will create an anonymous class, but it's hacky:

Set<String> h = new HashSet<String>() {{
    add("a");
    add("b");
}};

If you have only one value and want to get an immutable set this would be enough:

Set<String> immutableSet = Collections.singleton("a");

If the contained type of the Set is an enumeration then there is java built factory method (since 1.5):

Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... );

import com.google.common.collect.Sets;
Sets.newHashSet("a", "b");

or

import com.google.common.collect.ImmutableSet;
ImmutableSet.of("a", "b");

Just a small note, regardless of which of the fine approaches mentioned here you end up with, if this is a default that usually goes unmodified (like a default setting in a library you are creating), it is a good idea to follow this pattern:

// Initialize default values with the method you prefer, even in a static block
// It's a good idea to make sure these defaults aren't modifiable
private final static Set<String> DEFAULT_VALUES = Collections.unmodifiableSet(...);
private Set<String> values = DEFAULT_VALUES;

The benefit depends on the number of instances you create of that class and how likely it's that defaults will be changed.

If you decide to follow this pattern, then you also get to pick the method of set initialization that's most readable. As the micro differences in efficiency between the different methods will probably not matter much as you will be initializing the set only once.


With Eclipse Collections there are a few different ways to initialize a Set containing the characters 'a' and 'b' in one statement. Eclipse Collections has containers for both object and primitive types, so I illustrated how you could use a Set<String> or CharSet in addition to mutable, immutable, synchronized and unmodifiable versions of both.

Set<String> set =
    Sets.mutable.with("a", "b");
HashSet<String> hashSet =
    Sets.mutable.with("a", "b").asLazy().into(new HashSet<String>());
Set<String> synchronizedSet =
    Sets.mutable.with("a", "b").asSynchronized();
Set<String> unmodifiableSet =
    Sets.mutable.with("a", "b").asUnmodifiable();

MutableSet<String> mutableSet =
    Sets.mutable.with("a", "b");
MutableSet<String> synchronizedMutableSet =
    Sets.mutable.with("a", "b").asSynchronized();
MutableSet<String> unmodifiableMutableSet =
    Sets.mutable.with("a", "b").asUnmodifiable();

ImmutableSet<String> immutableSet =
    Sets.immutable.with("a", "b");
ImmutableSet<String> immutableSet2 =
    Sets.mutable.with("a", "b").toImmutable();

CharSet charSet =
    CharSets.mutable.with('a', 'b');
CharSet synchronizedCharSet =
    CharSets.mutable.with('a', 'b').asSynchronized();
CharSet unmodifiableCharSet =
    CharSets.mutable.with('a', 'b').asUnmodifiable();
MutableCharSet mutableCharSet =
    CharSets.mutable.with('a', 'b');
ImmutableCharSet immutableCharSet =
    CharSets.immutable.with('a', 'b');
ImmutableCharSet immutableCharSet2 =
    CharSets.mutable.with('a', 'b').toImmutable();

Note: I am a committer for Eclipse Collections.


This is an elegant solution:

public static final <T> Set<T> makeSet(@SuppressWarnings("unchecked") T... o) {
        return new HashSet<T>() {
            private static final long serialVersionUID = -3634958843858172518L;
            {
                for (T x : o)
                   add(x);
            }
        };
}

Combining answer by Michael Berdyshev with Generics and using constructor with initialCapacity, comparing with Arrays.asList variant:

  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Set;

  @SafeVarargs
  public static <T> Set<T> buildSetModif(final T... values) {
    final Set<T> modifiableSet = new HashSet<T>(values.length);
    Collections.addAll(modifiableSet, values);
    return modifiableSet;
  }

  @SafeVarargs
  public static <T> Set<T> buildSetModifTypeSafe(final T... values) {
    return new HashSet<T>(Arrays.asList(values));
  }

  @SafeVarargs
  public static <T> Set<T> buildeSetUnmodif(final T... values) {
    return Collections.unmodifiableSet(buildSetModifTypeSafe(values));
    // Or use Set.of("a", "b", "c") if you use Java 9
  }
  • This is good if you pass a few values for init, for anything large use other methods
  • If you accidentally mix types with buildSetModif the resulting T will be ? extends Object, which is probably not what you want, this cannot happen with the buildSetModifTypeSafe variant, meaning that buildSetModifTypeSafe(1, 2, "a"); will not compile

With the release of and the convenience factory methods this is possible in a cleaner way:

Set set = Set.of("a", "b", "c");

With Java 9 you can do the following:

Set.of("a", "b");

and you'll get an immutable Set containing the elements. For details see the Oracle documentation of interface Set.


There are a few ways:

Double brace initialization

This is a technique which creates an anonymous inner class which has an instance initializer which adds Strings to itself when an instance is created:

Set<String> s = new HashSet<String>() {{
    add("a");
    add("b");
}}

Keep in mind that this will actually create an new subclass of HashSet each time it is used, even though one does not have to explicitly write a new subclass.

A utility method

Writing a method that returns a Set which is initialized with the desired elements isn't too hard to write:

public static Set<String> newHashSet(String... strings) {
    HashSet<String> set = new HashSet<String>();

    for (String s : strings) {
        set.add(s);
    }
    return set;
}

The above code only allows for a use of a String, but it shouldn't be too difficult to allow the use of any type using generics.

Use a library

Many libraries have a convenience method to initialize collections objects.

For example, Google Collections has a Sets.newHashSet(T...) method which will populate a HashSet with elements of a specific type.


The Builder pattern might be of use here. Today I had the same issue. where I needed Set mutating operations to return me a reference of the Set object, so I can pass it to super class constructor so that they too can continue adding to same set by in turn constructing a new StringSetBuilder off of the Set that the child class just built. The builder class I wrote looks like this (in my case it's a static inner class of an outer class, but it can be its own independent class as well):

public interface Builder<T> {
    T build();
}

static class StringSetBuilder implements Builder<Set<String>> {
    private final Set<String> set = new HashSet<>();

    StringSetBuilder add(String pStr) {
        set.add(pStr);
        return this;
    }

    StringSetBuilder addAll(Set<String> pSet) {
        set.addAll(pSet);
        return this;
    }

    @Override
    public Set<String> build() {
        return set;
    }
}

Notice the addAll() and add() methods, which are Set returning counterparts of Set.add() and Set.addAll(). Finally notice the build() method, which returns a reference to the Set that the builder encapsulates. Below illustrates then how to use this Set builder:

class SomeChildClass extends ParentClass {
    public SomeChildClass(String pStr) {
        super(new StringSetBuilder().add(pStr).build());
    }
}

class ParentClass {
    public ParentClass(Set<String> pSet) {
        super(new StringSetBuilder().addAll(pSet).add("my own str").build());
    }
}

A bit convoluted but works from Java 5:

Set<String> h = new HashSet<String>(Arrays.asList(new String[] {  
    "a", "b"
}))

Use a helper method to make it readable:

Set<String> h = asSet ("a", "b");

public Set<String> asSet(String... values) {
    return new HashSet<String>(java.util.Arrays.asList(values));
}

I feel the most readable is to simply use google Guava:

Set<String> StringSet = Sets.newSet("a", "b", "c");

(ugly) Double Brace Initialization without side effects:

Set<String> a = new HashSet<>(new HashSet<String>() {{
    add("1");
    add("2");
}})

But in some cases, if we mentioned that is a good smell to make final collections unmutable, it could be really useful:

final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{
    add("1");
    add("2");
}})

In Java 8 I would use:

Set<String> set = Stream.of("a", "b").collect(Collectors.toSet());

This gives you a mutable Set pre-initialized with "a" and "b". Note that while in JDK 8 this does return a HashSet, the specification doesn't guarantee it, and this might change in the future. If you specifically want a HashSet, do this instead:

Set<String> set = Stream.of("a", "b")
                        .collect(Collectors.toCollection(HashSet::new));

You can do it in Java 6:

Set<String> h = new HashSet<String>(Arrays.asList("a", "b", "c"));

But why? I don't find it to be more readable than explicitly adding elements.


You can also use vavr:

import io.vavr.collection.HashSet;

HashSet.of("a", "b").toJavaSet();

If you are looking for the most compact way of initializing a set then that was in Java9:

Set<String> strSet = Set.of("Apple", "Ball", "Cat", "Dog");

===================== Detailed answer below =================================

Using Java 10 (Unmodifiable Sets)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

Here the collector would actually return the unmodifiable set introduced in Java 9 as evident from the statement set -> (Set<T>)Set.of(set.toArray()) in the source code.

One point to note is that the method Collections.unmodifiableSet() returns an unmodifiable view of the specified set (as per documentation). An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. But the method Collectors.toUnmodifiableSet() returns truly immutable set in Java 10.


Using Java 9 (Unmodifiable Sets)

The following is the most compact way of initializing a set:

Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");

We have 12 overloaded versions of this convenience factory method:

static <E> Set<E> of()

static <E> Set<E> of(E e1)

static <E> Set<E> of(E e1, E e2)

// ....and so on

static <E> Set<E> of(E... elems)

Then a natural question is why we need overloaded versions when we have var-args? The answer is: every var-arg method creates an array internally and having the overloaded versions would avoid unnecessary creation of object and will also save us from the garbage collection overhead.


Using Java 8 (Modifiable Sets)

Using Stream in Java 8.

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

// stream from an array (String[] stringArray)
Set<String> strSet2 = Arrays.stream(stringArray)
         .collect(Collectors.toCollection(HashSet::new));

// stream from a list (List<String> stringList)
Set<String> strSet3 = stringList.stream()
         .collect(Collectors.toCollection(HashSet::new));

Using Java 8 (Unmodifiable Sets)

Using Collections.unmodifiableSet()

We can use Collections.unmodifiableSet() as:

Set<String> strSet4 = Collections.unmodifiableSet(strSet1);

But it looks slightly awkward and we can write our own collector like this:

class ImmutableCollector {
    public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
        return Collector.of(HashSet::new, Set::add, (l, r) -> {
            l.addAll(r);
            return l;
        }, Collections::unmodifiablSet);
    }
}

And then use it as:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

### Using Collectors.collectingAndThen() Another approach is to use the method [`Collectors.collectingAndThen()`][6] which lets us perform additional finishing transformations:
import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

If we only care about Set then we can also use Collectors.toSet() in place of Collectors.toCollection(HashSet::new).


Using Java 8 we can create HashSet as:

Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));

And if we want unmodifiable set we can create a utility method as :

public static <T, A extends Set<T>> Collector<T, A, Set<T>> toImmutableSet(Supplier<A> supplier) {
        return Collector.of(
                supplier,
                Set::add, (left, right) -> {
                    left.addAll(right);
                    return left;
                }, Collections::unmodifiableSet);
    }

This method can be used as :

 Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new));

Can use static block for initialization:

private static Set<Integer> codes1=
        new HashSet<Integer>(Arrays.asList(1, 2, 3, 4));

private static Set<Integer> codes2 =
        new HashSet<Integer>(Arrays.asList(5, 6, 7, 8));

private static Set<Integer> h = new HashSet<Integer>();

static{
    h.add(codes1);
    h.add(codes2);
}

One of the most convenient ways is usage of generic Collections.addAll() method, which takes a collection and varargs:

Set<String> h = new HashSet<String>();
Collections.addAll(h, "a", "b");

A generalization of coobird's answer's utility function for creating new HashSets:

public static <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    for (T o : objs) {
        set.add(o);
    }
    return set;
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to collections

Kotlin's List missing "add", "remove", Map missing "put", etc? How to unset (remove) a collection element after fetching it? How can I get a List from some class properties with Java 8 Stream? Java 8 stream map to list of keys sorted by values How to convert String into Hashmap in java How can I turn a List of Lists into a List in Java 8? MongoDB Show all contents from all collections Get nth character of a string in Swift programming language Java 8 Distinct by property Is there a typescript List<> and/or Map<> class/library?

Examples related to constructor

Two constructors Class constructor type in typescript? ReactJS: Warning: setState(...): Cannot update during an existing state transition Inheritance with base class constructor with parameters What is the difference between using constructor vs getInitialState in React / React Native? Getting error: ISO C++ forbids declaration of with no type undefined reference to 'vtable for class' constructor Call asynchronous method in constructor? Purpose of a constructor in Java? __init__() missing 1 required positional argument

Examples related to initialization

"error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to declare an ArrayList with values? Initialize array of strings Initializing a dictionary in python with a key value and no corresponding values Declare and Initialize String Array in VBA VBA (Excel) Initialize Entire Array without Looping Default values and initialization in Java Initializing array of structures C char array initialization

Examples related to hashset

How to sort a HashSet? Does adding a duplicate value to a HashSet/HashMap replace the previous value How to Iterate over a Set/HashSet without an Iterator? How to calculate the intersection of two sets? Why there is no ConcurrentHashSet against ConcurrentHashMap Hashcode and Equals for Hashset Collection that allows only unique items in .NET? HashSet vs LinkedHashSet Define: What is a HashSet? Difference between HashSet and HashMap?