package com.insightfullogic.java8.answers.chapter3; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; /** * Advanced Exercises Question 1 */ public class FilterUsingReduce { public static <I> List<I> filter(Stream<I> stream, Predicate<I> predicate) { List<I> initial = new ArrayList<>(); return stream.reduce(initial, (List<I> acc, I x) -> { if (predicate.test(x)) { // We are copying data from acc to new list instance. It is very inefficient, // but contract of Stream.reduce method requires that accumulator function does // not mutate its arguments. // Stream.collect method could be used to implement more efficient mutable reduction, // but this exercise asks to use reduce method explicitly. List<I> newAcc = new ArrayList<>(acc); newAcc.add(x); return newAcc; } else { return acc; } }, FilterUsingReduce::combineLists); } private static <I> List<I> combineLists(List<I> left, List<I> right) { // We are copying left to new list to avoid mutating it. List<I> newLeft = new ArrayList<>(left); newLeft.addAll(right); return newLeft; } }