In this tutorial, we’re going to get through how to create an immutable Set in Java 9 by using convenience static factory methods of the Set interface, which have been added into Java 9.
1. Create An Immutable Set In Java 9 By Static Factory Methods
To create an immutable Set in Java 8, we can use the unmodifiableSet static method of Collections class, for example:
1 2 |
Set<String> japanNoodles = Collections.unmodifiableSet( new HashSet<>(Arrays.asList("Ramen", "Yakisoba", "Udon", "Soba", "Somen"))); |
We can see that the set was created in not a simple way in Java 8. However, Java 9 offers us a more convenient way to create an immutable Set by using Static Factory Methods which have been added recently. Let’s take a look at the method syntax:
1 2 3 4 5 |
Set.of() Set.of(e1) Set.of(e1, e2) // fixed-argument form overloads up to 10 elements ... Set.of(E... elements) // varargs form supports an arbitrary number of elements or an array |
Next, let see some examples about creating an immutable Set in Java 9 by using above convenience static factory methods of the Set interface.
Java 9 also provide us the convenience static factory methods of the List interface, please visit Create Immutable Lists In Java 9 By Static Factory Methods.
2. Characteristics Of The Immutable Set Static Factory Methods
As we can see from above, the List.of() static factory methods enable us a convenient way to create immutable sets. And the Setinstances created by these methods have the following characteristics:
- They are structurally immutable. Their elements cannot be added, removed, or replaced. If we do any mutator method, we will always get UnsupportedOperationException exception, for example:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Test public void testImmutableSetNotModified() { Set<String> japanNoodles = Set.of("Ramen", "Yakisoba", "Udon", "Soba", "Somen"); assertEquals(5, japanNoodles.size()); assertThrows(UnsupportedOperationException.class, () -> { // Add more element japanNoodles.add("Negi"); // Remove element japanNoodles.remove(1); }); } |
We attempt to add one more element into the immutable Set and get exception.
- The immutable Set can contain elements are themselves mutable, this may cause its contents to appear to change, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Test public void testImmutableSetMutableElements() { Map<Integer, String> noodleToppingsMap = new HashMap<>(); noodleToppingsMap.put(1, "Negi"); noodleToppingsMap.put(2, "Tamago"); noodleToppingsMap.put(3, "Nori"); Map<Integer, String> japanTeaMap = new HashMap<>(); japanTeaMap.put(1, "Ryokucha"); japanTeaMap.put(2, "Yamecha"); japanTeaMap.put(3, "Ujicha"); List<Map<Integer, String>> choices = List.of(noodleToppingsMap, japanTeaMap); assertEquals(3, choices.get(0).size()); //Add more elements to the mutable element of the List noodleToppingsMap.put(3, "Tsuyu"); choices.get(0).put(4, "Aracha"); assertEquals(4, choices.get(0).size()); } |
The choices is an immutable Set which contains 2 mutables Map: japanTeaMap and noodleToppingMap, and they are can change the contents.
- The convenience static factory methods of the Set interface disallows NULL elements. If we attempt to create them with null elements then a NullPointerException will be thrown, for example:
1 2 3 4 5 6 7 8 |
@Test public void testImmutableSetNullAttempts() { assertThrows(NullPointerException.class, () -> { Set<String> stringList = Set.of(null); }); } |
- The convenience static factory methods of the Set interface rejects duplicate elements at creation time. Duplicate elements passed to a static factory method result in IllegalArgumentException, for example:
1 2 3 4 5 6 7 8 |
@Test public void testImmutableSetRejectDupplicates() { assertThrows(IllegalArgumentException.class, () -> { Set<?> teaSet = Set.of("Shincha", "Aki Bancha", "Hojicha", "Hojicha"); }); } |
- They are serializable if all elements are serializable and they are serialized as specified on the Serialized Form page, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Test public void testImmutableSetSerializable() throws IOException { Set<String> drinks = Set.of("Gyokuro", "Tamaryokucha", "Kamairicha"); //serialize the list ObjectOutputStream oos = new ObjectOutputStream(System.out); oos.writeObject(drinks); //create a list of non-serializable objects List<OutputStream> outputStreamList = List.of(new ByteArrayOutputStream(), new PrintStream(System.out)); assertThrows(NotSerializableException.class, () -> { oos.writeObject(outputStreamList); } ); } |
3. Conclusion
The tutorial has illustrated about the immutable Set static factory methods and how to use those to create immutable Sets in Java 9. We can see that the immutable methods are very convenient for us to initialize a Set from known values, and that never changes. And we always should consider using these methods if our data changes infrequently.
The sample source code presented in the tutorial is available on my Github project. It’s a Maven based project, So it’s easy to be imported in Eclipse, IntelliJ IDEA, etc.
Below are other Java 9 related tutorials for your references:
Install Oracle Java 9 on CentOS, RHEL 7
Install Oracle Java 9 on Ubuntu 16.04 LTS (Xenial Xerus)
Private Interface Methods In Java 9
Using The InputStream.transferTo() To Copy Streams In Java 9
How To Compare Arrays In Java 9
Java 9 – Effectively Final Variables In try-with-resources
Java 9 HTTP/2 Client API Example