利用Stream聚合函數(shù)如何對(duì)BigDecimal求和
利用Stream聚合函數(shù)對(duì)BigDecimal求和
數(shù)據(jù)庫(kù)查找的結(jié)果經(jīng)常會(huì)有List等集合,而集合中存放法是JAVA對(duì)象,對(duì)象中存在BigDecimal的字段,如果用for或者iterator遍歷來(lái)累加感覺(jué)很麻煩,stream聚合函數(shù)很好的解決了這個(gè)問(wèn)題.做個(gè)筆記mark一下
POJO
package test; import java.math.BigDecimal; /** ?* 用戶實(shí)體類 ?* ?* @author suddev ?* @create 2018-02-26 上午11:03 ?**/ public class User { ? ? private long id; ? ? private BigDecimal money; ? ? public User(long id, BigDecimal money) { ? ? ? ? this.id = id; ? ? ? ? this.money = money; ? ? } ? ? // getter&setter }
在實(shí)體類中,我們可以看到實(shí)體存在一個(gè)為BigDecimal的money屬性,以計(jì)算所有查詢出來(lái)的用戶金錢總額為例子:
package test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; /** ?* 測(cè)試類 ?* ?* @author suddev ?* @create 2018-02-26 上午11:03 ?**/ public class Test { ? ? public static void main(String[] args) { ? ? ? ? // 準(zhǔn)備數(shù)據(jù) ? ? ? ? List<User> userList = new ArrayList<User>(); ? ? ? ? for (int i = 0; i < 100; i++) { ? ? ? ? ? ? User user = new User(i,new BigDecimal(i+"."+i)); ? ? ? ? ? ? userList.add(user); ? ? ? ? } ? ? ? ? // for version ? ? ? ? BigDecimal result1 = BigDecimal.ZERO; ? ? ? ? for (User user : userList) { ? ? ? ? ? ? result1 = result1.add(user.getMoney()); ? ? ? ? } ? ? ? ? System.out.println("result1 = "+result1); ? ? ? ? // java 8 stream version ? ? ? ? BigDecimal result2 = userList.stream() ? ? ? ? ? ? ? ? // 將user對(duì)象的mongey取出來(lái)map為Bigdecimal ? ? ? ? ? ? ? ? .map(User::getMoney) ? ? ? ? ? ? ? ? // 使用reduce聚合函數(shù),實(shí)現(xiàn)累加器 ? ? ? ? ? ? ? ? .reduce(BigDecimal.ZERO,BigDecimal::add); ? ? ? ? System.out.println("result2 = "+result2); ? ? } }
map
是一個(gè)對(duì)于流對(duì)象的中間操作,通過(guò)給定的方法,它能夠把流對(duì)象中的每一個(gè)元素對(duì)應(yīng)到另外一個(gè)對(duì)象上,這里將user對(duì)象的money取出來(lái)map為Bigdecimalreduce
是一個(gè)終結(jié)操作,它能夠通過(guò)某一個(gè)方法,對(duì)元素進(jìn)行削減操作。該操作的結(jié)果會(huì)放在一個(gè)Optional變量里返回??梢岳盟鼇?lái)實(shí)現(xiàn)很多聚合方法比如count,max,min等。
這里利用了reduce的第二個(gè)方法重載
Treduce(T identity, BinaryOperator accumulator);
第一個(gè)參數(shù)是我們給出的初值,第二個(gè)參數(shù)是累加器,可以自己用實(shí)現(xiàn)接口完成想要的操作,這里使用Bigdecimal的add方法
最后reduce會(huì)返回計(jì)算后的結(jié)果
Stream流,求和計(jì)算
Stream 是對(duì)集合(Collection)對(duì)象功能的增強(qiáng),它專注于對(duì)集合對(duì)象進(jìn)行各種非常便利、高效的聚合操作,或者大批量數(shù)據(jù)操作。通常我們需要多行代碼才能完成的操作,借助于Stream流式處理可以很簡(jiǎn)單的實(shí)現(xiàn)。
將分別使用傳統(tǒng)的foreach 和 stream流 進(jìn)行集合的求和匯總運(yùn)算,廢話不多說(shuō),直接上代碼
創(chuàng)建測(cè)試的實(shí)體類
@Data @ToString public class Sys_testClass implements Serializable { ? ? private String name;//名稱 ? ? private double price;//價(jià)格 ? ? private int number;//數(shù)量 ? ? private double sum_price;//商品總價(jià)格 }
插個(gè)題外話,上面的 @Date和@ToString 注解代替了我們自動(dòng)生成的getting,setting和toString方法,讓類看上去更簡(jiǎn)潔明了,并且當(dāng)你重新添加或刪除字段的時(shí)候,不用去管getting,setting方法,大大節(jié)省了開(kāi)發(fā)時(shí)間及效率,如果想用的小伙伴,直接導(dǎo)入 lombok依賴即可
創(chuàng)建 Main方法
并且往集合中添加測(cè)試數(shù)據(jù)
public static void main(String[] args) { ? ? List<Sys_testClass> listTest = new ArrayList<>(); ? ? Sys_testClass test1 = new Sys_testClass(); ? ? test1.setName("商品1"); ? ? test1.setPrice(3200.0); ? ? test1.setNumber(3); ? ? test1.setSum_price(test1.getPrice()*test1.getNumber()); ? ? listTest.add(test1); ? ? Sys_testClass test2 = new Sys_testClass(); ? ? test2.setName("商品2"); ? ? test2.setPrice(1599.0); ? ? test2.setNumber(6); ? ? test2.setSum_price(test2.getPrice()*test2.getNumber()); ? ? listTest.add(test2); ? ? Sys_testClass test3 = new Sys_testClass(); ? ? test3.setName("商品3"); ? ? test3.setPrice(999.0); ? ? test3.setNumber(2); ? ? test3.setSum_price(test3.getPrice()*test3.getNumber()); ? ? listTest.add(test3); }
利用傳統(tǒng)foreach循環(huán)遍歷
得到集合中所有價(jià)格的和,代碼如下
double sum_price=0.00; //價(jià)格總和的初始值 for (Sys_testClass sys_testClass : listTest) { ? ? sum_price+=sys_testClass.getSum_price();//循環(huán)相加 集合中的總價(jià)格 } System.err.println(sum_price);// 打印輸出值為: 21192.0
利用java8新特性(Stream流)遍及集合
只需要一行代碼
double sum_price = listTest.stream().mapToDouble(Sys_testClass::getSum_price).sum(); System.err.println(sum_price);//打印輸出值為: 21192.0
注:價(jià)格是double 類型,所以這里用了mapToDouble方法,如果是int類型求和 替換成 mapToInt方法即可
兩者相比可以看出傳統(tǒng)循環(huán)需要 4 行代碼,而新特性只需要 1 行代碼,速度上其實(shí)一樣的,底層都是循環(huán)遍歷得到結(jié)果,但是集合多了,開(kāi)發(fā)時(shí)間就將會(huì)大大節(jié)省
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何為Spark Application指定不同的JDK版本詳解
這篇文章主要給大家介紹了關(guān)于如何為Spark Application指定不同的JDK版本的相關(guān)資料,文中通過(guò)示例代碼將解決的方法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面來(lái)隨著小編一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11SpringBoot中的MongoTemplate的各種條件查詢示例詳解
這篇文章主要介紹了SpringBoot中的MongoTemplate的各種條件查詢示例詳解,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借價(jià)值,需要的朋友參考下吧2024-01-01Springboot事件監(jiān)聽(tīng)與@Async注解詳解
這篇文章主要介紹了Springboot事件監(jiān)聽(tīng)與@Async注解詳解,在開(kāi)發(fā)中經(jīng)??梢岳肧pring事件監(jiān)聽(tīng)來(lái)實(shí)現(xiàn)觀察者模式,進(jìn)行一些非事務(wù)性的操作,如記錄日志之類的,需要的朋友可以參考下2024-01-01解決Java項(xiàng)目啟動(dòng)報(bào)錯(cuò):Logback?configuration?error?detected:問(wèn)題
這篇文章主要介紹了解決Java項(xiàng)目啟動(dòng)報(bào)錯(cuò):Logback?configuration?error?detected:問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04SpringBoot深入分析講解監(jiān)聽(tīng)器模式上
監(jiān)聽(tīng)器模式,大家應(yīng)該并不陌生,主要的組成要素包括了事件、監(jiān)聽(tīng)器以及廣播器;當(dāng)事件發(fā)生時(shí),廣播器負(fù)責(zé)將事件傳遞給所有已知的監(jiān)聽(tīng)器,而監(jiān)聽(tīng)器會(huì)對(duì)自己感興趣的事件進(jìn)行處理2022-07-07基于spring boot實(shí)現(xiàn)一個(gè)全局異常處理器
在項(xiàng)目開(kāi)發(fā)中,我們可以基于spring boot提供的切面特性,來(lái)很輕松的實(shí)現(xiàn)全局異常的處理,所以本文主要為大家介紹了如何基于spring boot實(shí)現(xiàn)一個(gè)全局異常處理器,有需要的可以參考下2023-09-09springMVC幾種頁(yè)面跳轉(zhuǎn)方式小結(jié)
本篇文章主要介紹了springMVC 幾種頁(yè)面跳轉(zhuǎn)方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02