JavaDoc of ImmutableSet
says:
Unlike
Collections.unmodifiableSet
, which is a view of a separate collection that can still change, an instance of this class contains its own private data and will never change. This class is convenient for public static final sets ("constant sets") and also lets you easily make a "defensive copy" of a set provided to your class by a caller.
But the ImmutableSet
still stores reference of elements, I couldn't figure out the difference to Collections.unmodifiableSet()
. Sample:
StringBuffer s=new StringBuffer("a");
ImmutableSet<StringBuffer> set= ImmutableSet.of(s);
s.append("b");//s is "ab", s is still changed here!
Could anyone explain it?
Kevin Bourrillion (Guava lead developer) compares immutable / unmodifiable collections in this presentation. While the presentation is two years old, and focuses on "Google Collections" (which is now a subpart of Guava), this is a very interesting presentation. The API may have changed here and there (the Google Collections API was in Beta at the time), but the concepts behind Google Collections / Guava are still valid.
You might also be interested in this other SO question ( What is the difference between google's ImmutableList and Collections.unmodifiableList() ).
A difference between the two not stated in other answers is that
ImmutableSet
does not permitnull
values, as described in the Javadoc(The same restriction applies to values in all Guava immutable collections.)
For example:
All of these fail at runtime. In contrast:
This is fine.
Consider this:
In other words,
ImmutableSet
is immutable despite whatever collection it's built from potentially changing - because it creates a copy.Collections.unmodifiableSet
prevents the returned collection from being directly changed, but it's still a view on a potentially-changing backing set.Note that if you start changing the contents of the objects referred to by any set, all bets are off anyway. Don't do that. Indeed, it's rarely a good idea to create a set using a mutable element type in the first place. (Ditto maps using a mutable key type.)
Besides the behavioral difference that Jon mentions, an important difference between
ImmutableSet
and theSet
created byCollections.unmodifiableSet
is thatImmutableSet
is a type. You can pass one around and have it remain clear that the set is immutable by usingImmutableSet
rather thanSet
throughout the code. WithCollections.unmodifiableSet
, the returned type is justSet
... so it's only clear that the set is unmodifiable at the point where it is created unless you add Javadoc everywhere you pass thatSet
saying "this set is unmodifiable".