< prev index next >

src/java.base/share/classes/java/util/stream/Stream.java

Print this page

        

@@ -845,10 +845,161 @@
     <U> U reduce(U identity,
                  BiFunction<U, ? super T, U> accumulator,
                  BinaryOperator<U> combiner);
 
     /**
+     * Folds the elements of this stream using the provided seed object and
+     * accumulation function, going left to right. This is equivalent to:
+     *
+     * <pre>{@code
+     *     U result = seed;
+     *     for (T element : this stream)
+     *         result = accumulator.apply(result, element)
+     *     return result;
+     * }
+     * </pre>
+     *
+     * <p>This is a <a href="package-summary.html#StreamOps">terminal
+     * operation</a>.
+     *
+     * <p>This method cannot take all the advantages of parallel streams as it must
+     * process elements strictly left to right. If your accumulator function is
+     * associative and you can provide a combiner function, consider using
+     * {@link #reduce(Object, BiFunction, BinaryOperator)} method.
+     *
+     * @param <U> The type of the result
+     * @param seed the starting value
+     * @param accumulator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+     *                    <a href="package-summary.html#Statelessness">stateless</a>
+     *                    function for incorporating an additional element into a result
+     * @return the result of the folding
+     * @see #foldRight(Object, BiFunction)
+     * @see #reduce(Object, BinaryOperator)
+     * @see #reduce(Object, BiFunction, BinaryOperator)
+     * @since 10
+     */
+    default <U> U foldLeft(U seed, BiFunction<U, ? super T, U> accumulator) {
+        ReduceOps.FoldLeftWithSeedOp<U, ? super T> consumer = new ReduceOps.FoldLeftWithSeedOp<>(seed, accumulator);
+        forEachOrdered(consumer);
+        return consumer.get();
+    }
+
+    /**
+     * Folds the elements of this stream using the provided accumulation
+     * function, going left to right. This is equivalent to:
+     *
+     * <pre>{@code
+     *     boolean foundAny = false;
+     *     T result = null;
+     *     for (T element : this stream) {
+     *         if (!foundAny) {
+     *             foundAny = true;
+     *             result = element;
+     *         }
+     *         else
+     *             result = accumulator.apply(result, element);
+     *     }
+     *     return foundAny ? Optional.of(result) : Optional.empty();
+     * }
+     * </pre>
+     *
+     * <p>This is a <a href="package-summary.html#StreamOps">terminal
+     * operation</a>.
+     *
+     * <p>This method cannot take all the advantages of parallel streams as it must
+     * process elements strictly left to right. If your accumulator function is
+     * associative, consider using {@link #reduce(BinaryOperator)} method.
+     *
+     * @param accumulator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+     *        <a href="package-summary.html#Statelessness">stateless</a>
+     *        function for incorporating an additional element into a result
+     * @return the result of the folding
+     * @see #foldLeft(Object, BiFunction)
+     * @see #foldRight(BinaryOperator)
+     * @see #reduce(BinaryOperator)
+     * @since 10
+     */
+    default Optional<T> foldLeft(BinaryOperator<T> accumulator) {
+        ReduceOps.FoldLeftOp<T> consumer = new ReduceOps.FoldLeftOp<>(accumulator);
+        forEachOrdered(consumer);
+        return consumer.get();
+    }
+
+    /**
+     * Folds the elements of this stream using the provided seed object and
+     * accumulation function, going right to left.
+     *
+     * <p>This is a <a href="package-summary.html#StreamOps">terminal
+     * operation</a>.
+     *
+     * <p>As this method must process elements strictly right to left, it cannot
+     * start processing till all the previous stream stages complete. Also it
+     * requires intermediate memory to store the whole content of the stream as
+     * the stream natural order is left to right. If your accumulator function
+     * is associative and you can provide a combiner function, consider using
+     * {@link #reduce(Object, BiFunction, BinaryOperator)} method.
+     *
+     * @param <U> The type of the result
+     * @param seed the starting value
+     * @param accumulator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+     *        <a href="package-summary.html#Statelessness">stateless</a>
+     *        function for incorporating an additional element into a result
+     * @return the result of the folding
+     * @see #foldLeft(Object, BiFunction)
+     * @see #reduce(Object, BinaryOperator)
+     * @see #reduce(Object, BiFunction, BinaryOperator)
+     * @since 10
+     */
+    default <U> U foldRight(U seed, BiFunction<? super T, U, U> accumulator) {
+        Object[] array = toArray();
+        U result = seed;
+        for(int idx = array.length - 1; idx >= 0; idx--) {
+            @SuppressWarnings("unchecked")
+            T t = (T) array[idx];
+            result = accumulator.apply(t, result);
+        }
+        return result;
+    }
+
+    /**
+     * Folds the elements of this stream using the provided accumulation
+     * function, going right to left.
+     *
+     * <p>This is a <a href="package-summary.html#StreamOps">terminal
+     * operation</a>.
+     *
+     * <p>
+     * As this method must process elements strictly right to left, it cannot
+     * start processing till all the previous stream stages complete. Also it
+     * requires intermediate memory to store the whole content of the stream as
+     * the stream natural order is left to right. If your accumulator function
+     * is associative, consider using {@link #reduce(BinaryOperator)} method.
+     *
+     * @param accumulator a <a href="package-summary.html#NonInterference">non-interfering</a>,
+     *        <a href="package-summary.html#Statelessness">stateless</a>
+     *        function for incorporating an additional element into a result
+     * @return the result of the folding
+     * @see #foldRight(Object, BiFunction)
+     * @see #foldLeft(BinaryOperator)
+     * @see #reduce(BinaryOperator)
+     * @since 10
+     */
+    default Optional<T> foldRight(BinaryOperator<T> accumulator) {
+        Object[] array = toArray();
+        int idx = array.length;
+        if (idx == 0) return Optional.empty();
+        @SuppressWarnings("unchecked")
+        T result = (T) array[--idx];
+        while(idx > 0) {
+            @SuppressWarnings("unchecked")
+            T t = (T) array[--idx];
+            result = accumulator.apply(t, result);
+        }
+        return Optional.of(result);
+    }
+
+    /**
      * Performs a <a href="package-summary.html#MutableReduction">mutable
      * reduction</a> operation on the elements of this stream.  A mutable
      * reduction is one in which the reduced value is a mutable result container,
      * such as an {@code ArrayList}, and elements are incorporated by updating
      * the state of the result rather than by replacing the result.  This
< prev index next >