Summary
-------
Changing the `unmodifiable*` methods in `java.util.Collections` so they do not re-wrap unmodifiable collections in another unmodifiable collections. That is, make calls to the `umodifiable*` methods idempotent.
Problem
-------
The `unmodifiable*` methods in `Collections` will take an existing collection and return an unmodifiable view of it. These methods do not inspect their arguments to see if they are already an unmodifiable collection. In cases where a collection is already unmodifiable, they will wrap the collection in another unmodifiable view. This creates needless overhead. The problem of creating nested wrappers has been observed in the wild to consume excess CPU cycles and to cause stack overflow errors.
Solution
--------
Change the `unmodifiable*` wrapping methods to avoid wrapping if the argument is already of an appropriate class. This proposal specifies idempotency only for unmodifiable wrappers internal to `java.util.Collection`. We continue to wrap other unmodifiable classes in the standard libraries (e.g. collections introduced in JEP 269 that are produced by `List.of()` and similar) because of semantic inconsistencies between those collections and these wrappers.
Specification
-------------
The following methods in `Collections` will be modified:
* `unmodifiableCollection`
* `unmodifiableList`
* `unmodifiableMap`
* `unmodifiableNavigableMap`
* `unmodifiableNavigableSet`
* `unmodifiableSet`
* `unmodifiableSortedMap`
* `unmodifiableSortedSet`
In each we will check the class of the argument. If the argument's class is the same as the the class returned by the method we return the argument instead.
An `@implNote` will be added for each affected method stating "this method may return its argument if the argument is already unmodifiable."