1. Introduction

In this tutorial, we’re going to have a look at different ways of constructing an immutable set in Java.

But first, let’s understand the immutable set and see why we need it.

2. What Is an Immutable Set?

In general, an immutable object will not change its internal state once we create it. This makes it thread-safe by default. The same logic applies to immutable sets.

Let’s suppose we have a HashSet instance with some values. Making it immutable will create a “read-only” version of our set. Thus, any attempt to modify its state will throw UnsupportedOperationException.

So, why do we need it?

Certainly, the most common use case of an immutable set is a multi-threaded environment. So, we can share immutable data across the threads without worrying about the synchronization.

Meanwhile, there’s an important point to keep in mind: immutability pertains only to the set and not to its elements. Furthermore, we can modify the instance references of the set elements without a problem.

3. Create Immutable Sets in Core Java

With just the core Java classes at our disposal, we can use the Collections.unmodifiableSet() method to wrap the original Set.

First, let’s create a simple HashSet instance and initialize it with String values:

Set<String> set = new HashSet<>();
set.add("Canada");
set.add("USA");

Next, let’s wrap it up with Collections.unmodifiableSet():

Set<String> unmodifiableSet = Collections.unmodifiableSet(set);

Finally, to make sure our unmodifiableSet instance is immutable, let’s create a simple test case:

@Test(expected = UnsupportedOperationException.class)
public void testUnmodifiableSet() {
    // create and initialize the set instance

    Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
    unmodifiableSet.add("Costa Rica");
}

As we expect, the test will run successfully. Furthermore, the add() operation is prohibited on the unmodifiableSet instance and will throw UnsupportedOperationException.

Now, let’s change the initial set instance by adding the same value to it:

set.add("Costa Rica");

This way, we indirectly modify the unmodifiable set. So, when we print the unmodifiableSet instance:

[Canada, USA, Costa Rica]

As we can see, the “Costa Rica” item is also present in unmodifiableSet.

4. Create Immutable Sets in Java 9

Since Java 9, the Set.of(elements) static factory method is available for creating immutable sets:

Set<String> immutable = Set.of("Canada", "USA");

5. Create Immutable Sets in Guava

Another way that we can construct an immutable set is by using Guava’s ImmutableSet class. It copies the existing data into a new immutable instance. As a result, the data inside ImmutableSet won’t change when we alter the original Set.

Like the core Java implementation, any attempt to modify the created immutable instance will throw UnsupportedOperationException.

Now, let’s explore different ways of creating immutable instances.

**5.1. Using *ImmutableSet.***copyOf()

Simply put, the ImmutableSet.copyOf() method returns a copy of all the elements in the set:

Set<String> immutable = ImmutableSet.copyOf(set);

So, after changing the initial set, the immutable instance will stay the same:

[Canada, USA]

5.2. Using ImmutableSet.of()**

Similarly, with the ImmutableSet.of() method we can instantly create an immutable set with the given values:

Set<String> immutable = ImmutableSet.of("Canada", "USA");

When we don’t specify any elements, the ImmutableSet.of() will return an empty immutable set.

This can be compared to Java 9’s Set.of().

6. Conclusion

In this quick article, we discussed immutable Sets in the Java language. Moreover, we showed how to create immutable Sets using the Collections API from core Java, Java 9 and the Guava library.

Finally, as usual, the complete code for this article is available over on GitHub.


« 上一篇: Java @SafeVarargs 注解
» 下一篇: Java中的多维ArrayList