JAVA8?Stream流中的reduce()方法詳解
reduce()簡(jiǎn)介
Reduce原意:減少,縮小- 根據(jù)指定的計(jì)算模型將Stream中的值計(jì)算得到一個(gè)最終結(jié)果
解釋:reduce 操作可以實(shí)現(xiàn)從Stream中生成一個(gè)值,其生成的值不是隨意的,而是根據(jù)指定的計(jì)算模型。比如,之前提到count、min和max方法,因?yàn)槌S枚患{入標(biāo)準(zhǔn)庫中。事實(shí)上,這些方法都是reduce操作。
reduce三個(gè)override的方法
reduce方法有三個(gè)override的方法:
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);公共集合
測(cè)試代碼中的所有集合,都是該集合。
List<Person> javaProgrammers = new ArrayList<Person>() {
{
add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25));
add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25));
add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99));
add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14));
add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
}
};方式一reduce(BinaryOperator accumulator)
Optional<T> reduce(BinaryOperator<T> accumulator);
我們先看第一個(gè)變形,參數(shù)列表為一個(gè)函數(shù)接口BinaryOperator<T>,
BinaryOperator源碼:
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
}看BinaryOperator接口源碼,我們可以看到,它又繼承了BiFunction<T,T,T>.
另外,在BinaryOperator接口中又定義了另個(gè)靜態(tài)方法為minBy和maxBy,
上面我們提到BinaryOperator接口繼承了BiFunction<T,T,T>,我們看一下BiFunction<T,T,T>源碼:
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);//接收兩個(gè)參數(shù) t 和 u, 返回 R
}Bifunction中有一個(gè)apply方法,接收兩個(gè)參數(shù),返回一個(gè)結(jié)果
小結(jié): 不管是BinaryOperator類還是最終繼承的BiFunction類,在類上都有@FunctionalInterface注解,因此reduce(BinaryOperator<T> accumulator)方法需要一個(gè)函數(shù)式接口參數(shù),該函數(shù)式接口需要兩個(gè)參數(shù),返回一個(gè)結(jié)果(reduce中返回的結(jié)果會(huì)作為下次累加器計(jì)算的第一個(gè)參數(shù)),也就是累加器,最終得到一個(gè)Optional對(duì)象
測(cè)試示例代碼:
@Test
public void Test() {
int asInt = javaProgrammers.stream()
.mapToInt(Person::getSalary)//返回?cái)?shù)值流,減少拆箱封箱操作,避免占用內(nèi)存 IntStream
.reduce((x, y) -> x += y)// int
.getAsInt(); //return int
System.out.printf("方式一 reduce(BinaryOperator<T> accumulator) 求薪資測(cè)試結(jié)果:"+asInt);
/*解析:
1. reduce(BinaryOperator<T> accumulator) reduce方法接受一個(gè)函數(shù),這個(gè)函數(shù)有兩個(gè)參數(shù)
2. 第一個(gè)參數(shù)是上次函數(shù)執(zhí)行的返回值(也稱為中間結(jié)果),第二個(gè)參數(shù)是stream中的元素,這個(gè)函數(shù)把這兩個(gè)值相加,得到的和會(huì)被賦值給下次執(zhí)行這個(gè)函數(shù)的第一個(gè)參數(shù)
*注意:
1.第一次執(zhí)行的時(shí)候第一個(gè)參數(shù)的值是Stream的第一個(gè)元素,第二個(gè)參數(shù)是Stream的第二個(gè)元素
2.方法返回值類型是Optional
*/
}方式二reduce(T identity, BinaryOperator accumulator) T reduce(T identity, BinaryOperator<T> accumulator);
與第一種變形相同的是都會(huì)接受一個(gè)BinaryOperator函數(shù)接口,不同的是其會(huì)接受一個(gè)identity參數(shù),identity參數(shù)與Stream中數(shù)據(jù)同類型,相當(dāng)于一個(gè)的初始值,通過累加器accumulator迭代計(jì)算Stream中的數(shù)據(jù),得到一個(gè)跟Stream中數(shù)據(jù)相同類型的最終結(jié)果。
測(cè)試示例代碼:
@Test
public void test1(){
int reduce = javaProgrammers.stream().mapToInt(Person::getSalary).reduce(10000, (x, y) -> x += y);
System.out.printf("方式二 reduce(T identity, BinaryOperator<T> accumulator) 求薪資測(cè)試結(jié)果:"+reduce);
/*注意:
* 1.與方式一相比設(shè)置了累加器的初始值,參數(shù)一(x)則不再是Stream中的第一個(gè)數(shù)據(jù)而是設(shè)置的初始值(10000)其他相同
*/
}打印結(jié)果:
方式一 reduce(BinaryOperator<T> accumulator) 求薪資測(cè)試結(jié)果:57308
方式二 reduce(T identity, BinaryOperator<T> accumulator) 求薪資測(cè)試結(jié)果:67308 //初始值10000
方式三 reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)
\<U\> U reduce(U identity,BiFunction\<U, ? super T, U\> accumulator,BinaryOperator\<U\> combiner);
我們先觀察分析再次被改變的參數(shù)列表:
1. 第一個(gè)參數(shù):返回實(shí)例u,傳遞你要返回的U類型對(duì)象的初始化實(shí)例u
2. 第二個(gè)參數(shù):累加器accumulator,可以使用lambda表達(dá)式,聲明你在u上累加你的數(shù)據(jù)來源t的邏輯,例如(u,t)->u.sum(t),此時(shí)lambda表達(dá)式的行參列表是返回實(shí)例u和遍歷的集合元素t,函數(shù)體是在u上累加t
3. 第三個(gè)參數(shù):參數(shù)組合器combiner,接受lambda表達(dá)式。
根據(jù)參數(shù)我們一步一步分析代碼示例:
@Test
public void test2() {
ArrayList<Integer> accResult_ = Stream.of(1, 2, 3, 4)
//第一個(gè)參數(shù),初始值為ArrayList
.reduce(new ArrayList<Integer>(),
//第二個(gè)參數(shù),實(shí)現(xiàn)了BiFunction函數(shù)式接口中apply方法,并且打印BiFunction
new BiFunction<ArrayList<Integer>, Integer, ArrayList<Integer>>() {
@Override
public ArrayList<Integer> apply(ArrayList<Integer> acc, Integer item) {
acc.add(item);
System.out.println("item: " + item);
System.out.println("acc+ : " + acc);
System.out.println("BiFunction");
return acc;
}
//第三個(gè)參數(shù)---參數(shù)的數(shù)據(jù)類型必須為返回?cái)?shù)據(jù)類型,改參數(shù)主要用于合并多個(gè)線程的result值
// (Stream是支持并發(fā)操作的,為了避免競(jìng)爭(zhēng),對(duì)于reduce線程都會(huì)有獨(dú)立的result)
}, new BinaryOperator<ArrayList<Integer>>() {
@Override
public ArrayList<Integer> apply(ArrayList<Integer> acc, ArrayList<Integer> item) {
System.out.println("BinaryOperator");
acc.addAll(item);
System.out.println("item: " + item);
System.out.println("acc+ : " + acc);
System.out.println("--------");
return acc;
}
});
System.out.println("accResult_: " + accResult_);
System.out.println("------------------lambda優(yōu)化代碼-----------------");
ArrayList<Integer> newList = new ArrayList<>();
ArrayList<Integer> accResult_s = Stream.of(1,2,3,4)
.reduce(newList,
(acc, item) -> {
acc.add(item);
System.out.println("item: " + item);
System.out.println("acc+ : " + acc);
System.out.println("BiFunction");
return acc;
}, (acc, item) -> null);
System.out.println("accResult_s: " + accResult_s);
}
示例代碼中,第一個(gè)參數(shù)是ArrayList,在第二個(gè)函數(shù)參數(shù)中打印了“BiFunction”,而在第三個(gè)參數(shù)接口中打印了函數(shù)接口中打印了”BinaryOperator“.看下面的打印結(jié)果,只打印了“BiFunction”,而沒有打印”BinaryOperator“,也就是說第三個(gè)函數(shù)參數(shù)并沒有執(zhí)行。分析參數(shù)時(shí)我們知道了該變形可以返回任意類型的數(shù)據(jù)。
對(duì)于第三個(gè)函數(shù)參數(shù),為什么沒有執(zhí)行,而且其參數(shù)必須為返回的數(shù)據(jù)類型?這是因?yàn)镾tream是支持并發(fā)操作的,為了避免競(jìng)爭(zhēng),對(duì)于reduce線程都會(huì)有獨(dú)立的result,combiner的作用在于合并每個(gè)線程的result得到最終結(jié)果。這也說明了了第三個(gè)函數(shù)參數(shù)的數(shù)據(jù)類型必須為返回?cái)?shù)據(jù)類型了。
java8新特性之stream流中reduce()求和知識(shí)總結(jié)
打印結(jié)果:
item: 1
acc+ : [1]
BiFunction
item: 2
acc+ : [1, 2]
BiFunction
item: 3
acc+ : [1, 2, 3]
BiFunction
item: 4
acc+ : [1, 2, 3, 4]
BiFunction
另外需要注意:因?yàn)榈谌齻€(gè)參數(shù)用來處理并發(fā)操作,如何處理數(shù)據(jù)的重復(fù)性,應(yīng)多做考慮,否則會(huì)出現(xiàn)重復(fù)數(shù)據(jù)!
到此這篇關(guān)于JAVA8 Stream流中的reduce()方法詳解的文章就介紹到這了,更多相關(guān)JAVA8 Stream reduce()方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis實(shí)體類屬性與數(shù)據(jù)庫不一致解決方案
這篇文章主要介紹了Mybatis實(shí)體類屬性與數(shù)據(jù)庫不一致解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
通過實(shí)例講解springboot整合WebSocket
這篇文章主要介紹了通過實(shí)例講解springboot整合WebSocket,WebSocket為游覽器和服務(wù)器提供了雙工異步通信的功能,即游覽器可以向服務(wù)器發(fā)送消息,服務(wù)器也可以向游覽器發(fā)送消息。,需要的朋友可以參考下2019-06-06
Java接口操作(繼承父類并實(shí)現(xiàn)多個(gè)接口)
這篇文章主要介紹了Java接口操作(繼承父類并實(shí)現(xiàn)多個(gè)接口),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
Java基于UDP協(xié)議實(shí)現(xiàn)簡(jiǎn)單的聊天室程序
這篇文章主要為大家詳細(xì)介紹了Java基于UDP協(xié)議實(shí)現(xiàn)簡(jiǎn)單的聊天室程序的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Java后臺(tái)基于POST獲取JSON格式數(shù)據(jù)
這篇文章主要介紹了Java后臺(tái)基于POST獲取JSON格式數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
nacos服務(wù)注冊(cè)服務(wù)發(fā)現(xiàn)依賴配置詳解
這篇文章主要為大家介紹了nacos服務(wù)注冊(cè)服務(wù)發(fā)現(xiàn)依賴配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
java 中cookie的詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 中cookie的詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,這里對(duì)cookie 的建立與讀取,和設(shè)定cookie 生命周期等詳細(xì)介紹,需要的朋友可以參考下2017-01-01
java中treemap和treeset實(shí)現(xiàn)紅黑樹
這篇文章主要為大家詳細(xì)介紹了java中treemap和treeset實(shí)現(xiàn)紅黑樹,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11

