Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is an efficient and elegant way to add a single element to an immutable set?

Tags:

java

guava

I have an immutable set (cast as a Set<Integer>) that potentially contains many elements. I need a Collection that contains the elements from that set plus one additional element. I have kludgy code in place to copy the set, then append the element, but I'm looking for The Right Way that keeps things as efficient as possible.

I have Guava available, though I do not require its use.

like image 270
Max Avatar asked Apr 27 '12 16:04

Max


People also ask

How can we set a set to immutable?

Yes, Java provides a method named unmodifiableSet() in the Collections class. This method accepts a collection object as a parameter and returns an unmodifiable i.ie immutable form of it.

Can we add element to immutable list?

We cannot add, update or remove elements in an immutable List . An immutable List is completely immutable only if its containing objects are also immutable.

How can we add immutable list?

add(element) " is because this method is designed to be able to add elements to ImmutableList s. Those are, quite obviously, immutable (if you look, their native add method throws an UnsupportedOperationException ) and so the only way to "add" to them is to create a new list.

How do you add elements to an unmodifiable list?

copyOf. If you want an independent and truly immutable second list, use List. copyOf in Java 10+. This returns an unmodifiable list.


2 Answers

Not sure about performance, but you can use Guava's ImmutableSet.Builder:

import com.google.common.collect.ImmutableSet  // ... Set<Integer> newSet = new ImmutableSet.Builder<Integer>()                                 .addAll(oldSet)                                 .add(3)                                 .build(); 

Of course you can also write yourself a helper method for that:

public static <T> Set<T> setWith(Set<T> old, T item) {   return new ImmutableSet.Builder<T>().addAll(old).add(item).build(); }  // ... Set<Integer> newSet = setWith(oldSet, 3); 
like image 200
Niklas B. Avatar answered Sep 17 '22 12:09

Niklas B.


Using Java 8 you can also use streams for that effect

Stream.concat(oldSet.stream(),               Stream.of(singleElement))       .collect(Collectors.toSet()) 

By the way since JDK 10, the Collectors also allow to accumulate to immutable types (the same as the ones created by the static factories like Set.of()) :

Stream.concat(oldSet.stream(),               Stream.of(singleElement))       .collect(Collectors.toUnmodifiableSet()) 
like image 29
Brice Avatar answered Sep 21 '22 12:09

Brice