讓天下沒有難學的javajava
點贊、關注、收藏 安全
reduce是什麼?簡單來說我認爲的reduce就是一個歸一化的迭代操做。接受一個stream,經過重複應用操做將他們組合成一個簡單結果。app
若是要與collect做對比的話,一般狀況下collect返回的是List<T>,Set<T>,Map<T>...,而reduce一般只返回T(可是T是泛型,實際上你能夠返回包括List在類的任意類型)。ide
本文主要介紹三個參數的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;
}
}));
}
複製代碼
打印結果、線程名極可能不會不一致,ArrayList非線程安全。(若是Collections.synchronizedList(a)包裝下元素卻是不會少)。ui
着重看System.out.println(acc==item);。每次accumulator的第二個參數與第一個參數中ArrayList同樣。spa
若是將List<Integer> a 轉成Collections.synchronizedList(a),那麼順序不必定一致,可是元素必定是全的。線程
//大概示意圖3d