RFR: 8368178: Add specialization of SequencedCollection methods to emptyList, singletonList and nCopies

Tagir F. Valeev tvaleev at openjdk.org
Sun Sep 21 10:47:11 UTC 2025


On Sat, 20 Sep 2025 20:36:43 GMT, Pavel Rappo <prappo at openjdk.org> wrote:

>> Please review this small change. If you have more ideas which classes may miss specializations of SequencedCollection methods, I can add them to this PR as well.
>
>> If you have more ideas which classes may miss specializations of SequencedCollection methods, I can add them to this PR as well.
> 
> Have you considered something like this?
> 
> diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java
> index 38cc45122a2..d8c3499a958 100644
> --- a/src/java.base/share/classes/java/util/ImmutableCollections.java
> +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java
> @@ -352,7 +352,7 @@ public boolean contains(Object o) {
>  
>          @Override
>          public List<E> reversed() {
> -            return ReverseOrderListView.of(this, false);
> +            return size() < 2 ? this : ReverseOrderListView.of(this, false);
>          }
>  
>          IndexOutOfBoundsException outOfBounds(int index) {
> @@ -636,6 +636,11 @@ public int lastIndexOf(Object o) {
>              }
>          }
>  
> +        @Override
> +        public List<E> reversed() {
> +            return size() == 1 ? this : super.reversed();
> +        }
> +
>          @java.io.Serial
>          private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
>              throw new InvalidObjectException("not serial proxy");

@pavelrappo re `ImmutableCollections`, I was thinking about them. One thing that bugs me is that `List.copyOf(immutableList)` doesn't copy, but `List.copyOf(immutableList.reversed())` produces a fresh copy. Probably this is not a very common scenario to optimize, though.

Re `List12.reversed()` with size == 2: probably it's better to create a fresh list like `new List12<>(e1, e0)`, like


        @SuppressWarnings("unchecked")
        @Override
        public List<E> reversed() {
            return e1 == EMPTY ? this : new List12<>((E) e1, e0);
        }


This way, we have fewer indirections and always return the instance of `List12`, which may probably help with devirtualization sometimes. The `List12` instance size is small. With compressed OOPs it's likely the same size as `ReverseOrderListView` (two object fields, compared to object+boolean fields in `ReverseOrderListView`), and the original list could become eligible for GC. One downside of this approach is that `listOf2.reversed().reversed()` will return a fresh instance, rather than the original one. But I guess it's a rare scenario and the cost is still small. What do you think?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/27406#issuecomment-3315911606


More information about the core-libs-dev mailing list