简体   繁体   中英

Regarding unmodifiable collection

Consider the following code below

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        List<Integer> intList1=new ArrayList<Integer>();
        List<Integer> intList2;
        intList1.add(1);
        intList1.add(2);
        intList1.add(3);
        intList2=Collections.unmodifiableList(intList1);
        intList1.add(4);

        for(int i=0;i<4;i++)
        {
            System.out.println(intList2.get(i));
        }
    }

}

The result of the above code is

1
2
3
4

In the above code we create an unmodifiable List intList2 from the contents of the List intList 1. But after the Collections.unmodifiable statement when I make a change to intList1 that change reflects to intList2 . How is this possible ?

You need to read the Javadoc for Collections.unmodifiableList

Returns an unmodifiable view of the specified list.

This means that the returned view is unmodifiable. If you have the original reference you can change the collection. If you change the collection then changes will be reflected in the view.

This has the advantage of being very fast, ie you don't need to copy the collection, but the disadvantage that you noted - the resulting collection is a view.

In order to create a truly unmodifiable collection you would need to copy then wrap:

intList2=Collections.unmodifiableList(new ArrayList<>(intList1));

This copies the contents of intList1 into another collection then wraps that collection in the unmodifiable variable. No reference to the wrapped collection exists.

This is expensive - the entire underlying datastore (an array in this case) needs to duplicated which (generally) takes O(n) .

Google Guava provides immutable collections which solve some of the problems of making defensive copies:

  • If a collection is already immutable it is not copied again
  • Provide an interface which can be used to explicitly state that a collection is immutable
  • Provide numerous static factory methods to generate immutable collections

But speed is still the key concern when using immutable copies of collections rather than unmodifiable views.

It should be noted that the usual use for Collections.unmodifiableXXX is to return from a method, for example a getter:

public Collection<Thing> getThings() {
    return Collections.unmodifiableCollection(things);
}

In this case there are two things to note:

  1. The user of getThings cannot access things so the unmodifiability cannot be broken.
  2. It would be very expensive to copy things each time a getter were called.

In summary the answer to your question is a little more complex than you might have expected and there are a number of aspects to consider when passing collections around in your application.

From the Javadoc of Collections.unmodifiableList:

Returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists.

It prevent the returned list to be modified, but the original list itself still can be.

Collections.unmodifiableList returns a "read-only" view of the internal list. While the object that was returned is not modifiable the original list that it references can be modified. Both objects point to the same object in memory so it will reflect changes made.

Here is a good explanation of what is happening.

发生这种情况是因为无法修改的列表在内部支持第一个列表,如果您真的希望它不可修改,则不应再使用第一个列表。

In your code you are

 intList2=Collections.unmodifiableList(intList1);

creating unmodifiableList in intList2. So you are free to make changes in inList1 but you are not allowed to do any changes in intList2

try this: intList2.add(4); you will get

 java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Unknown Source)

above exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM