20

If you have a List<String> strings instance, would you keep writing:

Collections.unmodifiableList(strings)

or switch to:

List.of(strings.toArray(new String[strings.size()]))

What's the initial impact in performance (memory- and runtime-wise) of instantion? Is there a runtime benefit in the List.of variant?

Sormuras
  • 8,491
  • 1
  • 38
  • 64
  • The runtime benefit is with `unmodifiableList` on creation. And if `strings` is an `ArrayList` there is no reason for `List.of`. – Joop Eggen Sep 08 '16 at 08:29
  • Possible duplicate of [What is the difference between List.of and Arrays.asList?](https://stackoverflow.com/questions/46579074/what-is-the-difference-between-list-of-and-arrays-aslist) – Mark Oct 06 '17 at 15:16
  • https://stackoverflow.com/a/72591708/7930516 – AriyaDey Jan 25 '23 at 10:13

2 Answers2

23

This is not really a good comparison because these approaches do different things:

  • Collections::unmodifiable... creates an unmodifiable view. It is not immutable because it changes if you're changing the original, backing collection (list in your example).
  • ...::of on the other hand, creates an immutable copy. Changing the original list will not affect it.

From a performance view it is obvious that creation of the unmodifiable wrapper is cheaper because it only creates one instance with a single field. The new factory methods will create at least one object, maybe backed by an array (if you have three or more elements), that it needs to copy into.

Access could be faster on the new immutable collections but that would have to be benchmarked.

But correctness trumps performance. What do you need? If you need an immutable copy, use the new methods (or Guava's Immutable..., which I would prefer). If you need something immutable, use unmodifiable... and throw away the original (and make sure it stays like that). If you need a view that your caller can not edit, use unmodifiable....

Nicolai Parlog
  • 47,972
  • 24
  • 125
  • 255
  • I'd say this is a very logical comparison. How shall one intuitively deduce, that `..::of` creates what you have described here they create and `::unmodifiable...` - what you say they do, in such a granularity? Also, naming of the types or variables *must* be speaking of themselves.. and I really don't know how would one guess, that `List.of(...)` is 1) immutable, and 2) differs from unmodifiable. `ImmutableList.of(..)` would have been much better then. Modification and Mutation are quite ambiguously and overlappingly defined terms in this context. Unmodifiable.. cannot be modified.. mutated.. – Giorgi Tsiklauri Mar 01 '23 at 08:29
  • @GiorgiTsiklauri One should not intuitively deduce that - one should read the Javadoc. What this answer was trying to express: The semantics of the two methods are different, so pick the one with the correct semantics, not the one that may (or may not) be more performant under certain circumstances. – Nicolai Parlog Apr 01 '23 at 14:04
5

According to JEP 269 (Convenience Factory Methods for Collections):

Goals

Provide static factory methods on the collection interfaces that will create compact, unmodifiable collection instances. The API is deliberately kept minimal.

Non-Goals

  • It is not a goal to provide a fully-general "collection builder" facility that, for example, lets the user control the collection implementation or various characteristics such as mutability, expected size, loading factor, concurrency level, and so forth.

  • It is not a goal to support high-performance, scalable collections with arbitrary numbers of elements. The focus is on small collections.

  • It is not a goal to provide unmodifiable collection types. That is, this proposal does not expose the characteristic of unmodifiability in the type system, even though the proposed implementations are actually unmodifiable.

  • It is not a goal to provide "immutable persistent" or "functional" collections.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    Add a synopsis of what you want to express: your point is not entirely clear, though I can guess. – Joop Eggen Sep 08 '16 at 08:40
  • Are `Collections.unmodifiableXyz` methods build for high-performance? Maybe a JMH test will show the difference. My use-case copes 99% with small lists. That would go conform with the goal of JEP 269. – Sormuras Sep 08 '16 at 08:46