Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between Collections.unmodifiableSet() and ImmutableSet of Guava?

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?

like image 496
卢声远 Shengyuan Lu Avatar asked Apr 10 '11 11:04

卢声远 Shengyuan Lu


People also ask

Are collections Emptyset mutable?

We can use Collections. EMPTY_SET that returns an immutable, serializable, and empty set. Guava provides several static utility methods that can be used to obtain an immutable empty set.

How do you make a set immutable?

Using Of() method of Java9 The of() method of Java9 accepts list of elements, creates and returns an immutable set with the given elements. Using this method, you can create an immutable set in Java.

How do you make a Java collection immutable?

In Java 8 and earlier versions, we can use collection class utility methods like unmodifiableXXX to create immutable collection objects. If we need to create an immutable list then use the Collections. unmodifiableList() method.


3 Answers

Consider this:

Set<String> x = new HashSet<String>();
x.add("foo");

ImmutableSet<String> guava = ImmutableSet.copyOf(x);
Set<String> builtIn = Collections.unmodifiableSet(x);

x.add("bar");
System.out.println(guava.size()); // Prints 1
System.out.println(builtIn.size()); // Prints 2

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.)

like image 144
Jon Skeet Avatar answered Oct 19 '22 09:10

Jon Skeet


Besides the behavioral difference that Jon mentions, an important difference between ImmutableSet and the Set created by Collections.unmodifiableSet is that ImmutableSet is a type. You can pass one around and have it remain clear that the set is immutable by using ImmutableSet rather than Set throughout the code. With Collections.unmodifiableSet, the returned type is just Set... so it's only clear that the set is unmodifiable at the point where it is created unless you add Javadoc everywhere you pass that Set saying "this set is unmodifiable".

like image 20
ColinD Avatar answered Oct 19 '22 09:10

ColinD


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() ).

like image 10
Etienne Neveu Avatar answered Oct 19 '22 09:10

Etienne Neveu