< prev index next >

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

Print this page

        

*** 845,854 **** --- 845,1005 ---- <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 >