Suppose I have the following Set
Set<String> fruits = new HashSet<String>();
fruits.add("Apple")
fruits.add("Grapes")
fruits.add("Orange")
If I wanted to create a defensive copy, so that if the original list is modified, the copy doesn't reflect it, I can do this:
Set<String> unmodifiableFruits = Collections.unmodifiableSet(new HashSet(fruits))
so if I do this:
fruits.add("Pineapple")
println(unmodifiableFruits)
unmodifiableFruits won't have pineapple.
or I can so this:
Set<String> unmodifiableFruits = Collections.unmodifiableCollection(fruits)
and the result is the same, unmodifiableFruits won't have pineapple.
Questions:
- Suppose if I were passing
fruitsas an argument to a class, is the preferred method theCollections.unmodifiableCollection()?
The reason is, I've read that declaring new in the constructor is a bad practice, if I were to use Collections.unmodifiableSet(), I would need to declare a new HashSet<String>(fruits).
Why can't I do this ?
Collections.unmodifiableSet(fruits)
and have it return an unmodifiable collection.
instead I have to do this:
Collections.unmodifiableSet(new HashSet<String>(fruits))
Is it because Set is an interface and it doesn't know which implementation to return?
Groovy has enhanced collection methods, meaning that it has added methods to the standard collection classes.
Once of those methods is
toSet():When you write this:
it implies a
.toSet()call to coerce theCollectionreturned byunmodifiableCollectioninto aSet, implicitly copying the data.When you write this:
the returned value is already a
Set, sotoSet()is not called, meaning thatunmodifiableFruitsandfruitsshare data.That is why you have to explicitly copy the data when using
unmodifiableSet, by addingnew HashSet(...).Absolutely not. Using
unmodifiableCollection()and assigning to aSet, implicitly invokingtoSetwhich copies the data, is hiding the fact that a copy is executed.To ensure code readability, i.e. that anyone reading the code (including yourself in 3 years) will understand what it does, write the code to explicitly copy the data, using the copy-constructor.
Well, of course, unless this is an exercise in code obfuscation, in which case it's a nice misleading trick.