Seems that the patch attachment was filtered out. Just for the case
here it is:

diff --git a/src/java.base/share/classes/java/util/Collections.java 
b/src/java.base/share/classes/java/util/Collections.java
--- a/src/java.base/share/classes/java/util/Collections.java
+++ b/src/java.base/share/classes/java/util/Collections.java
@@ -4702,43 +4702,7 @@
      * @return A singleton {@code Spliterator}
      */
     static <T> Spliterator<T> singletonSpliterator(final T element) {
-        return new Spliterator<T>() {
-            long est = 1;
-
-            @Override
-            public Spliterator<T> trySplit() {
-                return null;
-            }
-
-            @Override
-            public boolean tryAdvance(Consumer<? super T> consumer) {
-                Objects.requireNonNull(consumer);
-                if (est > 0) {
-                    est--;
-                    consumer.accept(element);
-                    return true;
-                }
-                return false;
-            }
-
-            @Override
-            public void forEachRemaining(Consumer<? super T> consumer) {
-                tryAdvance(consumer);
-            }
-
-            @Override
-            public long estimateSize() {
-                return est;
-            }
-
-            @Override
-            public int characteristics() {
-                int value = (element != null) ? Spliterator.NONNULL : 0;
-
-                return value | Spliterator.SIZED | Spliterator.SUBSIZED | 
Spliterator.IMMUTABLE |
-                       Spliterator.DISTINCT | Spliterator.ORDERED;
-            }
-        };
+        return new ConstantSpliterator<>(1, element);
     }
 
     /**
@@ -5061,20 +5025,64 @@
             return new CopiesList<>(toIndex - fromIndex, element);
         }
 
-        // Override default methods in Collection
-        @Override
-        public Stream<E> stream() {
-            return IntStream.range(0, n).mapToObj(i -> element);
-        }
-
-        @Override
-        public Stream<E> parallelStream() {
-            return IntStream.range(0, n).parallel().mapToObj(i -> element);
-        }
-
         @Override
         public Spliterator<E> spliterator() {
-            return stream().spliterator();
+            return new ConstantSpliterator<>(n, element);
+        }
+    }
+    
+    private static final class ConstantSpliterator<T> implements 
Spliterator<T> {
+        long est;
+        T element;
+
+        public ConstantSpliterator(long est, T element) {
+            this.est = est;
+            this.element = element;
+        }
+
+        @Override
+        public Spliterator<T> trySplit() {
+            long est = this.est;
+            if (est >= 2) {
+                est >>= 1;
+                Spliterator<T> prefix = new ConstantSpliterator<>(est, 
element);
+                this.est -= est;
+                return prefix;
+            }
+            return null;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super T> action) {
+            Objects.requireNonNull(action);
+            if (est <= 0)
+                return false;
+            action.accept(element);
+            est--;
+            return true;
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super T> action) {
+            Objects.requireNonNull(action);
+            T element = this.element;
+            for (long r = est; r > 0; r--) {
+                action.accept(element);
+            }
+            est = 0;
+        }
+        
+        @Override
+        public long estimateSize() {
+            return est;
+        }
+
+        @Override
+        public int characteristics() {
+            int nonNull = (element != null) ? NONNULL : 0;
+            int distinct = (est <= 1) ? DISTINCT : 0; 
+
+            return SIZED | SUBSIZED | IMMUTABLE | ORDERED | nonNull | distinct;
         }
     }
 

With best regards,
Tagir Valeev.


TFV> Hello!

PS>> With reuse it becomes more compelling :-) In both cases of
PS>> singleton/nCopies the spliterator characteristics can be the same
PS>> and that of the already existing singleton spliterator implementation.

TFV> The only difference is the DISTINCT characteristic. I think it's good
TFV> to report it based on the list size, so
TFV> Collections.nCopies(1, obj).spliterator() can report DISTINCT as well.

PS>> I would be happy to accept a patch (with tests, if existing tests
PS>> do not cover this already, i suspect they might but we still need
PS>> to check). Have you signed the OCA [1]. If so i can accept a patch
PS>> from you and publish as a webrev for review.

TFV> Here's my patch to the Collections class. Implementation of the
TFV> ConstantSpliterator is added, singletonSpliterator method now uses it
TFV> as well as CopiesList::spliterator. CopiesList::stream and
TFV> CopiesList::parallelStream methods are removed as unnecessary.

TFV> The resulting bytecode is roughly 750 bytes less after applying my
TFV> patch.

TFV> As for tests, it seems that
TFV> test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
TFV> covers both singletonSpliterator and nCopies().spliterator() pretty
TFV> well. I checked that these tests succeed with my changes while failed
TFV> when some mistake in ConstantSpliterator is introduced. If you think
TFV> that  more  tests are necessary, please suggest what exactly should be
TFV> tested and where to put them.

TFV> With best regards,
TFV> Tagir Valeev.

Reply via email to