让天下没有难学的java
reduce是什么?简单来讲我认为的reduce就是一个归一化的迭代操作。接受一个stream,通过重复应用操作将他们组合成一个简单结果。
如果要与collect作对比的话,通常情况下collect返回的是List<T>,Set<T>,Map<T>...,而reduce通常只返回T(但是T是泛型,实际上你可以返回包括List在类的任意类型)。
本文主要介绍三个参数的reduce(),并行、非线程安全、及combiner。
Optional<T> reduce(BinaryOperator<T> accumulator); T reduce(T identity,BinaryOperator<T> accumulator); <U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner); 复制代码
/*** * @param: accumulator * @return: Optional */ Optional<T> reduce(BinaryOperator<T> accumulator); 复制代码
public class Main { public static void main(String[] args) { List<Integer> list = Lists.newArrayList(1,2,3,4,5); list.stream().reduce( new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer + integer2; } })); //=====等价于===== System.out.println(IntStream.range(1, 100).reduce((v1, v2) -> v1 + v2).orElse(0)); //=====等价于===== System.out.println(IntStream.range(1, 100).reduce(Integer::sum).orElse(0)); } } integer=1===integer2=2 integer=3===integer2=3 integer=6===integer2=4 integer=10===integer2=5 复制代码
public class Main { public static void main(String[] args) { List<Integer> list = Lists.newArrayList(1,2,3,4,5); //初始值100 list.stream().reduce( 100, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { System.out.println("integer="+integer+"===integer2="+integer2); return integer + integer2; } })); } } //初始值是100,不是1。比没有初始值的reduce多迭代1次。 integer=100===integer2=1 integer=101===integer2=2 integer=103===integer2=3 integer=106===integer2=4 integer=110===integer2=5 复制代码
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner); 复制代码
=====> (T t,U u)-> (R)r 复制代码
@FunctionalInterface public interface BiFunction<T, U, R> { R apply(T t, U u); default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); } } 复制代码
public static void main(String[] args) { ArrayList<Integer> accResult = Stream.of(1, 3, 5, 7) .reduce(new ArrayList<>(), new BiFunction<ArrayList<Integer>, Integer, ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> integers, Integer item) { System.out.println("before add: " + integers); System.out.println("item= " + item); integers.add(item); System.out.println("after add : " + integers); System.out.println("In BiFunction"); return integers; } }, new BinaryOperator<ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> integers, ArrayList<Integer> integers2) { integers.addAll(integers2); System.out.println("integers: " + integers); System.out.println("integers2: " + integers2); System.out.println("In BinaryOperator"); return integers; } }); System.out.println("accResult: " + accResult); } 复制代码
public static void main(String[] args) { ArrayList<Integer> accResult = Stream.of(1, 3, 5, 7).parallel() .reduce(new ArrayList<>(), new BiFunction<ArrayList<Integer>, Integer, ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> integers, Integer item) { integers.add(item); return integers; } }, new BinaryOperator<ArrayList<Integer>>() { @Override public ArrayList<Integer> apply(ArrayList<Integer> integers, ArrayList<Integer> integers2) { integers.addAll(integers2); System.out.println("thread name="+Thread.currentThread().getName()+" ==== integers=" + integers); System.out.println("integers2: " + integers2); System.out.println("In BinaryOperator"); return integers; } }); //打印结果几乎每次都不同 System.out.println("accResult: " + accResult); } 复制代码
public static void main(String[] args) { System.out.println( Stream.of(1, 2, 3, 4).parallel().reduce(5, new BiFunction<Integer, Integer, Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer + integer2; } } , new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer + integer2; } })); } 复制代码
5.2、如果第一个参数是ArrayList等对象而非基本数据类型或String,那么结果跟我们想的可能很不一样。
打印结果、线程名很可能不会不一致,ArrayList非线程安全。(如果Collections.synchronizedList(a)包装下元素倒是不会少)。
着重看System.out.println(acc==item);。每次accumulator的第二个参数与第一个参数中ArrayList一样。
如果将List<Integer> a 转成Collections.synchronizedList(a),那么顺序不一定一致,但是元素一定是全的。
//大概示意图