Guava: the magic of the ImmutableList of the copyOf () method

I would like to feel the "magic power" of the copyOf() method for Guava guava-libraries .

There is a small application that I use to test it.

Here is the documentation :

The JDK provides Collections.unmodifiableXXX methods, but in our opinion, it could be

  • bulky and verbose; unpleasant to use wherever you want to make protective copies.
  • unsafe: returned collections are truly immutable if no one references the original collection

So, I'm trying to build a model where "someone holds a reference to the original collection" . Thus, when working with a copy of the collection, I should not worry about changing the cost of the copy. But magic does not work yet (there are two attempts: 1. copyOf(collection) , 2. copyOf(iterator) ):

 import com.google.common.collect.ImmutableList; import java.util.LinkedList; import java.util.List; class MyObject { String name; public MyObject(String name) {this.name = name;} @Override public String toString() { return name; } } public class ListUnsafe { List<MyObject> list = new LinkedList<MyObject>(); { list.add(new MyObject("a")); list.add(new MyObject("b")); list.add(new MyObject("c")); } public List<MyObject> getList() { return ImmutableList.copyOf(list); } public List<MyObject> getCopyIterator() { return ImmutableList.copyOf(list.iterator()); } public static void main(String[] args) { ListUnsafe obj = new ListUnsafe(); { MyObject ref = obj.list.get(0); List<MyObject> myList = obj.getList(); MyObject copyObj = myList.get(0); copyObj.name = "new"; System.out.println("ref: " + ref); } obj = new ListUnsafe(); { MyObject ref = obj.list.get(0); List<MyObject> myList = obj.getCopyIterator(); MyObject copyObj = myList.iterator().next(); copyObj.name = "new"; System.out.println("ref: " + ref); } } } 

Output:

 ref: new ref: new 

This means that we have changed the source data. What we did not want.

Question

Why doesn't he copy?
How is it different from unmodifiableXXX ?

There is a link to a similar question:

The answer says about copyOf :

  • (from source) copyOf(collection) instance does not create temporary ArrayList ( copyOf(Iterable) and copyOf(iterator) do this).
+4
source share
2 answers
  • ImmutableList does not magically make elements immutable; This is a list that cannot be changed, not the elements contained in it.
  • ImmutableList.copyOf makes a copy if it does not copy a list that is already an ImmutableList . If you call ImmutableList.copyOf(list) twice for the same immutable list, you will get two different copies.
+15
source

First of all, thanks for all the answers. I came up with an example that satisfies me. This shows the difference between ImmutableSet.copyOf(..) and JDK Collections.unmodifiableSet(..);

And yes: it does shallow copy (otherwise it was strange because it was magic).

 class Person { public Person(String name) {this.name = name;} public Person(String name, Person relation) {this(name);this.relation = relation;} String name; Person relation; } public class ImmutableExample { public static void main(String[] args) { Person bob = new Person("bob"); Person chris = new Person("chris", bob); Person nullPerson = null; // NULL! final Set<Person> originalSet = new LinkedHashSet<Person>(Arrays.asList( bob, chris // nullPerson // NULL ! <- if we use null then we can not convert it to ImmutableSet )); Set<Person> googleSet = ImmutableSet.copyOf(originalSet); Set<Person> javaSet = Collections.unmodifiableSet(originalSet); // is it SAFE to delete someone from original collection? originalSet.remove(chris); // google for (Person person : googleSet) System.out.println(person.name); // Chris is still here! And this is good! Stay with us, Chris! // java standard for (Person person : javaSet) System.out.println(person.name); // Where is Chris ?? //newSet.add(new Person("newGuy")); // UnsupportedOperationException } } 

(The goal of the original question, although it provided the client with an absolutely safe reading list. But this can only be achieved by manually cloning all the objects in the list [if they are not immutable]. To provide something that is even better (in terms of immutability and concurrency security) than CopyOnWriteArrayList . I mean: it provides a secure iterator , but not the data itself, if it is mutable in the return list - the client can still change the data using references to the returned (by getter) data elements)

+4
source

Source: https://habr.com/ru/post/1482871/


All Articles