Hot questions for Operating Immutable Collections in Guava

Top 10 Java Open Source / Guava / Operating Immutable Collections

Java 8 collector for Guava immutable collections?

Question: I really like Java 8 streams and Guava's immutable collections, but I can't figure out how to use the two together.

For example, how do I implement a Java 8 Collector that gathers stream results into an ImmutableMultimap?

Bonus points: I'd like to be able to provide key/value mappers, similar to how Collectors.toMap() works.

Answer: Since version 21, you can

.collect(ImmutableSet.toImmutableSet())
.collect(Maps.toImmutableEnumMap())
.collect(Sets.toImmutableEnumSet())
.collect(Tables.toTable())
.collect(ImmutableList.toImmutableList())
.collect(Multimaps.toMultimap(...))

Is guava's ImmutableXXX really immutable?

Question: I have been using guava for some time now and truly trusted it, until I stumbled of an example yesterday, which got me thinking. Long story short, here it is:

 public static void testGuavaImmutability(){
     StringBuilder stringBuilder = new StringBuilder("partOne");
     ImmutableList<StringBuilder> myList = ImmutableList.of(stringBuilder);
     System.out.println(myList.get(0));
     stringBuilder.append("appended");
     System.out.println(myList.get(0));
 }

After running this you can see that the value of an entry inside an ImmutableList has changed. If two threads were involved here, one could happen to not see the updated of the other.

Also the thing that makes me very impatient for an answer is that Item15 in Effective Java, point five says this:

Make defensives copies in the constructor - which seems pretty logic.

Looking at the source code of the ImmutableList, I see this:

SingletonImmutableList(E element) {
     this.element = checkNotNull(element);
 }

So, no copy is actually made, although I have no idea how a generic deep copy would be implemented in such a case (may be serialization?).

why are they called Immutable then?

Answer: What you're getting at here is the difference between immutable and deeply immutable.

An immutable object will never change, but anything that it refers to might change. Deep immutability is much stronger: neither the base object nor any object you can navigate to from it will change.

Each is appropriate in its own situations. When you create your own class that has a field of type Date, that date is owned by your object; it's truly a part of it. Therefore, you should make defensive copies of it (on the way in and the way out!) to provide deep immutability.

But a collection does not really "own" its elements. Their states are not considered part of the collection's state; it is a different type of class -- a container. (Furthermore, as you allude, it has no deep knowledge of what element type is being used, so it wouldn't know how to copy the elements anyway.)

Another answer states that the Guava collections should have used the term unmodifiable. But there is a very well-defined difference between the terms unmodifiable and immutable in the context of collections, and it has nothing to do with shallow vs. deep immutability. "Unmodifiable" says you cannot change this instance, via the reference you have; "immutable" means this instance cannot change, period, whether by you or any other actor.