changeset 7157:b624065ad930

- replace NodeFactory.truncateToNode with Node.truncate. This allows for future truncation optimizations over the current default method implementations on Node and Node.OfPrimitive.
author psandoz
date Fri, 25 Jan 2013 10:09:32 +0100
parents 99b1d495328b
children 5c4de0891836
files src/share/classes/java/util/stream/Node.java src/share/classes/java/util/stream/NodeFactory.java src/share/classes/java/util/stream/Nodes.java src/share/classes/java/util/stream/SliceOp.java
diffstat 4 files changed, 100 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/Node.java	Fri Jan 25 10:02:12 2013 +0100
+++ b/src/share/classes/java/util/stream/Node.java	Fri Jan 25 10:09:32 2013 +0100
@@ -89,6 +89,10 @@
      */
     void copyInto(T[] array, int offset);
 
+    default Node<T> truncate(long from, long to, IntFunction<T[]> generator) {
+        return Nodes.truncateNode(this, from, to, generator);
+    }
+
     /**
      * Return the number of elements contained by this node
      */
@@ -182,6 +186,9 @@
             throw new UnsupportedOperationException();
         }
 
+        @Override
+        OfPrimitive<E> truncate(long from, long to, IntFunction<E[]> generator);
+
         /**
          * A specialization of a {@link java.util.stream.Sink} to build a flat primitive node whose contents
          * is all the pushed values.
@@ -234,6 +241,11 @@
 
         @Override
         void copyInto(int[] array, int offset);
+
+        @Override
+        default OfPrimitive<Integer> truncate(long from, long to, IntFunction<Integer[]> generator) {
+            return Nodes.truncateIntNode(this, from, to);
+        }
     }
 
     interface OfLong extends OfPrimitive<Long> {
@@ -267,6 +279,11 @@
 
         @Override
         void copyInto(long[] array, int offset);
+
+        @Override
+        default OfPrimitive<Long> truncate(long from, long to, IntFunction<Long[]> generator) {
+            return Nodes.truncateLongNode(this, from, to);
+        }
     }
 
     interface OfDouble extends OfPrimitive<Double> {
@@ -300,5 +317,10 @@
 
         @Override
         void copyInto(double[] array, int offset);
+
+        @Override
+        default OfPrimitive<Double> truncate(long from, long to, IntFunction<Double[]> generator) {
+            return Nodes.truncateDoubleNode(this, from, to);
+        }
     }
 }
--- a/src/share/classes/java/util/stream/NodeFactory.java	Fri Jan 25 10:02:12 2013 +0100
+++ b/src/share/classes/java/util/stream/NodeFactory.java	Fri Jan 25 10:09:32 2013 +0100
@@ -26,14 +26,13 @@
 
 import java.util.List;
 import java.util.Spliterator;
+import java.util.function.IntFunction;
 
 interface NodeFactory<T> {
     Node<T> emptyNode();
 
     Node<T> concNodes(List<Node<T>> nodes);
 
-    Node<T> truncateToNode(long size, Spliterator<T> spliterator, long skip, long targetSize, java.util.function.IntFunction<T[]> generator);
-
     /**
      * Make a node builder.
      *
@@ -44,5 +43,5 @@
      *                    the builder has reached capacity.
      * @return the node builder.
      */
-    Node.Builder<T> makeNodeBuilder(long sizeIfKnown, java.util.function.IntFunction<T[]> generator);
+    Node.Builder<T> makeNodeBuilder(long sizeIfKnown, IntFunction<T[]> generator);
 }
--- a/src/share/classes/java/util/stream/Nodes.java	Fri Jan 25 10:02:12 2013 +0100
+++ b/src/share/classes/java/util/stream/Nodes.java	Fri Jan 25 10:09:32 2013 +0100
@@ -47,6 +47,29 @@
         return new CollectionNode<>(c);
     }
 
+    public static<T> Node<T> truncateNode(Node<T> n, long from, long to, IntFunction<T[]> generator) {
+        long size = truncatedSize(n.count(), from, to);
+        if (size == 0)
+            return emptyNode();
+
+        Spliterator<T> spliterator = n.spliterator();
+        Node.Builder<T> nodeBuilder = Nodes.makeBuilder(size, generator);
+        nodeBuilder.begin(size);
+        for (int i = 0; i < from && spliterator.tryAdvance(e -> { }); i++) { }
+        for (int i = 0; (i < size) && spliterator.tryAdvance(nodeBuilder); i++) { }
+        nodeBuilder.end();
+        return nodeBuilder.build();
+    }
+
+    private static long truncatedSize(long size, long from, long to) {
+        if (from >= 0)
+            size = Math.max(0, size - from);
+        long limit = to - from;
+        if (limit >= 0)
+            size = Math.min(size, limit);
+        return size;
+    }
+
     /**
      * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
      * node builder.
@@ -119,6 +142,20 @@
         }
     }
 
+    public static Node.OfPrimitive<Integer> truncateIntNode(Node.OfPrimitive<Integer> n, long from, long to) {
+        long size = truncatedSize(n.count(), from, to);
+        if (size == 0)
+            return emptyPrimitiveNode();
+
+        Spliterator.OfPrimitive<Integer> spliterator = n.spliterator();
+        Node.OfPrimitive.Builder<Integer> nodeBuilder = Nodes.intMakeBuilder(size);
+        nodeBuilder.begin(size);
+        for (int i = 0; i < from && spliterator.tryAdvance((IntBlock) e -> { }); i++) { }
+        for (int i = 0; (i < size) && spliterator.tryAdvance((IntBlock) nodeBuilder); i++) { }
+        nodeBuilder.end();
+        return nodeBuilder.build();
+    }
+
     /**
      * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
      * node builder.
@@ -171,6 +208,20 @@
         }
     }
 
+    public static Node.OfPrimitive<Long> truncateLongNode(Node.OfPrimitive<Long> n, long from, long to) {
+        long size = truncatedSize(n.count(), from, to);
+        if (size == 0)
+            return emptyPrimitiveNode();
+
+        Spliterator.OfPrimitive<Long> spliterator = n.spliterator();
+        Node.OfPrimitive.Builder<Long> nodeBuilder = Nodes.longMakeBuilder(size);
+        nodeBuilder.begin(size);
+        for (int i = 0; i < from && spliterator.tryAdvance((LongBlock) e -> { }); i++) { }
+        for (int i = 0; (i < size) && spliterator.tryAdvance((LongBlock) nodeBuilder); i++) { }
+        nodeBuilder.end();
+        return nodeBuilder.build();
+    }
+
     /**
      * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
      * node builder.
@@ -223,6 +274,20 @@
         }
     }
 
+    public static Node.OfPrimitive<Double> truncateDoubleNode(Node.OfPrimitive<Double> n, long from, long to) {
+        long size = truncatedSize(n.count(), from, to);
+        if (size == 0)
+            return emptyPrimitiveNode();
+
+        Spliterator.OfPrimitive<Double> spliterator = n.spliterator();
+        Node.OfPrimitive.Builder<Double> nodeBuilder = Nodes.doubleMakeBuilder(size);
+        nodeBuilder.begin(size);
+        for (int i = 0; i < from && spliterator.tryAdvance((DoubleBlock) e -> { }); i++) { }
+        for (int i = 0; (i < size) && spliterator.tryAdvance((DoubleBlock) nodeBuilder); i++) { }
+        nodeBuilder.end();
+        return nodeBuilder.build();
+    }
+
     /**
      * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
      * node builder.
@@ -843,6 +908,11 @@
         }
 
         @Override
+        public OfPrimitive<Object> truncate(long from, long to, IntFunction<Object[]> generator) {
+            return this;
+        }
+
+        @Override
         public long count() {
             return 0;
         }
@@ -1546,20 +1616,6 @@
         }
 
         @Override
-        public Node<T> truncateToNode(long size,
-                                      Spliterator<T> spliterator,
-                                      long skip,
-                                      long targetSize,
-                                      java.util.function.IntFunction<T[]> generator) {
-            Node.Builder<T> nodeBuilder = Nodes.makeBuilder(size, generator);
-            nodeBuilder.begin(size);
-            for (int i = 0; i < skip && spliterator.tryAdvance(e -> { }); i++) { }
-            for (int i = 0; ((targetSize == -1) || (i < targetSize)) && spliterator.tryAdvance(nodeBuilder); i++) { }
-            nodeBuilder.end();
-            return nodeBuilder.build();
-        }
-
-        @Override
         public Node.Builder<T> makeNodeBuilder(long sizeIfKnown, java.util.function.IntFunction<T[]> generator) {
             return Nodes.makeBuilder(sizeIfKnown, generator);
         }
@@ -1577,21 +1633,6 @@
         }
 
         @Override
-        public Node<Integer> truncateToNode(long size,
-                                            Spliterator<Integer> spliterator,
-                                            long skip,
-                                            long targetSize,
-                                            java.util.function.IntFunction<Integer[]> generator) {
-            Node.OfPrimitive.Builder<Integer> nodeBuilder = Nodes.intMakeBuilder(size);
-            nodeBuilder.begin(size);
-            Spliterator.OfPrimitive<Integer> adapted = AbstractPipeline.adapt(spliterator);
-            for (int i = 0; i < skip && adapted.tryAdvance((IntBlock) e -> { }); i++) { }
-            for (int i = 0; ((targetSize == -1) || (i < targetSize)) && adapted.tryAdvance(nodeBuilder); i++)  { }
-            nodeBuilder.end();
-            return nodeBuilder.build();
-        }
-
-        @Override
         public Node.OfPrimitive.Builder<Integer> makeNodeBuilder(long sizeIfKnown,
                                                                  java.util.function.IntFunction<Integer[]> generator) {
             return Nodes.intMakeBuilder(sizeIfKnown);
@@ -1610,21 +1651,6 @@
         }
 
         @Override
-        public Node<Long> truncateToNode(long size,
-                                         Spliterator<Long> spliterator,
-                                         long skip,
-                                         long targetSize,
-                                         java.util.function.IntFunction<Long[]> generator) {
-            Node.OfPrimitive.Builder<Long> nodeBuilder = Nodes.longMakeBuilder(size);
-            nodeBuilder.begin(size);
-            Spliterator.OfPrimitive<Long> adapted = AbstractPipeline.adapt(spliterator);
-            for (int i = 0; i < skip && adapted.tryAdvance((LongBlock) e -> { }); i++) { }
-            for (int i = 0; ((targetSize == -1) || (i < targetSize)) && adapted.tryAdvance(nodeBuilder); i++)  { }
-            nodeBuilder.end();
-            return nodeBuilder.build();
-        }
-
-        @Override
         public Node.OfPrimitive.Builder<Long> makeNodeBuilder(long sizeIfKnown,
                                                               java.util.function.IntFunction<Long[]> generator) {
             return Nodes.longMakeBuilder(sizeIfKnown);
@@ -1643,21 +1669,6 @@
         }
 
         @Override
-        public Node<Double> truncateToNode(long size,
-                                           Spliterator<Double> spliterator,
-                                           long skip,
-                                           long targetSize,
-                                           java.util.function.IntFunction<Double[]> generator) {
-            Node.OfPrimitive.Builder<Double> nodeBuilder = Nodes.doubleMakeBuilder(size);
-            nodeBuilder.begin(size);
-            Spliterator.OfPrimitive<Double> adapted = AbstractPipeline.adapt(spliterator);
-            for (int i = 0; i < skip && adapted.tryAdvance((DoubleBlock) e -> { }); i++) { }
-            for (int i = 0; ((targetSize == -1) || (i < targetSize)) && adapted.tryAdvance(nodeBuilder); i++)  { }
-            nodeBuilder.end();
-            return nodeBuilder.build();
-        }
-
-        @Override
         public Node.OfPrimitive.Builder<Double> makeNodeBuilder(long sizeIfKnown,
                                                                 java.util.function.IntFunction<Double[]> generator) {
             return Nodes.doubleMakeBuilder(sizeIfKnown);
--- a/src/share/classes/java/util/stream/SliceOp.java	Fri Jan 25 10:02:12 2013 +0100
+++ b/src/share/classes/java/util/stream/SliceOp.java	Fri Jan 25 10:09:32 2013 +0100
@@ -340,15 +340,16 @@
             }
             else {
                 if (results.size() == 0) {
-                    if (offset+thisNodeSize >= targetOffset)
+                    if (offset + thisNodeSize >= targetOffset)
                         results.add(truncateNode(getLocalResult(),
                                                  Math.max(0, targetOffset - offset),
                                                  targetSize >= 0 ? Math.max(0, offset + thisNodeSize - (targetOffset + targetSize)) : 0));
                 }
                 else {
-                    if (targetSize == -1 || offset < targetOffset+targetSize) {
-                        results.add(truncateNode(getLocalResult(), 0,
-                                                 targetSize >= 0 ? Math.max(0, offset+thisNodeSize - (targetOffset + targetSize)) : 0));
+                    if (targetSize == -1 || offset < targetOffset + targetSize) {
+                        results.add(truncateNode(getLocalResult(),
+                                                 0,
+                                                 targetSize >= 0 ? Math.max(0, offset + thisNodeSize - (targetOffset + targetSize)) : 0));
                     }
                 }
             }
@@ -358,9 +359,7 @@
             if (skipLeft == 0 && skipRight == 0)
                 return input;
             else {
-                // @@@ Implement Node.truncate which will be more efficient
-                long truncatedSize = thisNodeSize - skipLeft - skipRight;
-                return helper.getOutputNodeFactory().truncateToNode(truncatedSize, input.spliterator(), skipLeft, truncatedSize, helper.arrayGenerator());
+                return input.truncate(skipLeft, thisNodeSize - skipRight, helper.arrayGenerator());
             }
         }
     }