2

I understand that List.of and List.copyOf create immutable clone lists of the original list, so in my understanding, the below code should print [1], [1, 2] when it actually prints [[1, 2]], [1, 2]? how does List.of take the most recent view of the initial collection, col?

Collection<Number> col = new HashSet<>();
col.add(1);
var list1 = List.of(col); //1
col.add(2); //2
var list2 = List.copyOf(col); //3
System.out.println(list1+", "+list2);
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
M.B
  • 49
  • 6

3 Answers3

8

List.of creates a new list with the parameters as elements. List.copyOf creates a new list with the same elements as the single Collection argument.

Pseudocode Examples (note the square brackets):

List.of(1,2,3) == [1,2,3]
List.copyOf([1,2,3]) == [1,2,3]
List.of([1,2,3]) == [[1,2,3]]
List.of([1,2,3], [4,5,6]) == [[1,2,3], [4,5,6]]

The third line is similar to what's happening in your code. of creates a list that has the parameters as elements. What parameters did you give it? One modifiable set. So it creates an unmodifiable list with a single element, that element being your modifiable set. Note also that of does not copy the set.

copyOf creates an unmodifiable list with the same elements as the collection that you passed in. You passed in col, which has the elements 1, 2, so it creates an unmodifiable List with the elements 1, 2.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Wonderful! thank you so much for the explanation @Sweeper. Much appreciated it. – M.B Dec 01 '20 at 04:00
  • Maybe add that the variable `list1` has the type `List>` and that the variable `list2` has the (expected?) type `List`. That made it clearer for me. – mnsc Jan 25 '23 at 12:49
  • And maybe add that there exist a confusing overload `List.of(E... elements)` meaning that if you pass an array to `of()` it actually behaves as `copyOf()` – mnsc Jan 25 '23 at 12:55
3

When you do List.of(col), you don't actually add elements into it, you add the whole hashset (as a reference), so when you add an item later into the hashset, it is displayed later.

Ecto
  • 1,125
  • 1
  • 7
  • 13
  • Thank you Ecto! Much appreciated, I like the explanation that List.of is actually pointing to the reference. Thank you. – M.B Dec 01 '20 at 04:04
2

Both will create unmodifiable lists. But with copyOf, subsequent changes to the underlying collection will not propagate, i.e. won't be visible through list2 in this case.

For example, if you add

col.add(3);

you'll find the change is reflected in list1, but not list2.

You may also find this post helpful: Java-How can i use correctly list.copyOf?

See the Java docs here for more info: https://docs.oracle.com/javase/10/docs/api/java/util/List.html#unmodifiable

Also: https://docs.oracle.com/javase/10/docs/api/java/util/List.html#copyOf(java.util.Collection)

costaparas
  • 5,047
  • 11
  • 16
  • 26