Why don't the unmodifiable methods from Collections class, create collections with new elements?

Suppose there is this code:

List<String> modifiableList = new ArrayList<String>(Arrays.asList("1","2","3"));
List<String> unmodifiableList = Collections.unmodifiableList(modifiableList);
System.out.println(unmodifiableList);
modifiableList.remove("1");
modifiableList.remove("3");
System.out.println(unmodifiableList);

it prints

[1, 2, 3]
[2]

If changing the second line to

List<String> unmodifiableList = Collections.unmodifiableList(
                                       new ArrayList<String>(modifiableList));

it works as expected. The question is why doesn't the UnmodifiableList inner class from Collections (and all the other unmodifiable classes) from there create a fresh copy of the original list, as does the constructor of ArrayList for example in order to really make it unmodifiable?

Edit: I understand what the code does; my question is why was it implemented this way? Why does the constructor from the UnmodifiableList (inner class from Collections) behave like the constructor of ArrayList in creating a fresh copy of the underlying array? Why a modifiable collection (ArrayList) copies the whole content while an unmodifiable collection doesn't?

Jon Skeet
people
quotationmark

Well the purpose of the methods is to create an unmodifiable view on an existing collection. That's the documented behaviour, and in many cases it's exactly what you want - it's much more efficient than copying all the data, for example... or you want to hand callers collections which will reflect any changes you want to make, but without allowing them to make changes.

If you want an immutable copy of the data (or at least the references...) then just create a copy and then create an immutable view over the top of it - just as you are.

So basically, you can easily create either a view or a copy-and-view, based on Collections.unmodifiable* themselves performing the view operation. So we have two orthogonal operations:

  • Create a copy (e.g. via the constructor)
  • Create a view (via Collections.unmodifiable*)

Those operations can be composed very easily. If Collections.unmodifiable* actually performed a "copy only" then we'd require other operations in order to just make a view. If you accept that both options are useful in different situations, making them composable gives lots of flexibility.

people

See more on this question at Stackoverflow