stream distinct去重_再来看看Java的新特性——Stream流
為什么要使用流?
摘要中已經(jīng)說(shuō)明了,為了提高開(kāi)發(fā)效率。流可以幫助我們高效操作集合,流幫助我們通過(guò)流水線(xiàn)的方式對(duì)集合進(jìn)行刪減、合并、排序、修改,并最終返回我們想要的元素?cái)?shù)據(jù)或統(tǒng)計(jì)數(shù)據(jù)。流水線(xiàn)的意思是說(shuō),一批元素不需要等待全部元素都完成某步操作,才進(jìn)行下步操作,而是可以盡早進(jìn)行下步操作,就好像流水線(xiàn)工廠(chǎng)一樣,這為流高效運(yùn)作提供了基礎(chǔ)。流還有一個(gè)內(nèi)部迭代的概念,就是把for循環(huán)顯示迭代隱藏起來(lái)了,這樣可以更方便的并行開(kāi)發(fā)。
流的使用
準(zhǔn)備
在使用流之前需要做些準(zhǔn)備,首先說(shuō)明兩個(gè)概念:中間操作 和 終端操作。中間操作就好比生產(chǎn)車(chē)間的一步一步元素處理,每步處理之后,里面的元素樣式或者數(shù)據(jù)結(jié)構(gòu)可能發(fā)生改變了,但是它還是流。終端操作就好比產(chǎn)品生產(chǎn)完了,要打包裝箱,變成最終消費(fèi)者可見(jiàn)的最終形態(tài),此時(shí),它已經(jīng)是產(chǎn)品,不再是流了。
接著為了演示操作,先模擬幾條數(shù)據(jù)
List<JSONObject> menu = new ArrayList<>(); menu.add(new JSONObject().putOpt("name","宮保雞丁").putOpt("price","28")); menu.add(new JSONObject().putOpt("name","魚(yú)香肉絲").putOpt("price","30")); menu.add(new JSONObject().putOpt("name","肉夾饃").putOpt("price","6")); menu.add(new JSONObject().putOpt("name","煎餅").putOpt("price","6"));常用的中間操作
filter
filter應(yīng)該是Stream操作里面最常見(jiàn)的了,過(guò)濾器顧名思義就是過(guò)濾數(shù)據(jù)用的,filter的參數(shù)可以是lambda表達(dá)式。
//比如下面這句話(huà),就是得到所有價(jià)格小于10的食物,得到的還是流。 //stream()方法將集合轉(zhuǎn)成流 menu.stream().filter(jsonObject -> jsonObject.getInt("price")<10);distinct 、 limit 和 skip
distinct是去重,limit是截取前幾個(gè)元素,skip是跳過(guò)前多少個(gè)元素。
List<Integer> integerList = new ArrayList<>(); integerList.add(1); integerList.add(1); integerList.add(2); integerList.add(3); integerList.stream().distinct()//經(jīng)過(guò)去重,流還剩1、2、3.skip(1)//跳過(guò)第一個(gè)元素,流中還有2、3.limit(1);//截取第一個(gè)元素,流中還剩2map
map映射,上面的filter是將元素篩選,map則是改變?cè)氐臉邮健1热?#xff0c;我們想要知道所有小于10塊食物的名字。
menu.stream().filter(jsonObject -> jsonObject.getInt("price")<10)//此時(shí)還是jsonObject.map(jsonObject -> jsonObject.getStr("name"));//此時(shí)變成了StringflatMap
流的合并,可以將多個(gè)數(shù)組合并操作,這樣返回元素不是流,而是具體元素本身了。
Stream.of(menu,foreignMenu)//此時(shí)元素是流 List<Stream>.flatMap(x -> x.stream())//此時(shí)元素是jsonObject List<jsonObject>.map(jsonObject -> jsonObject.getStr("name")).distinct();常用的終端方法
allMatch、anyMatch、noneMatch、findFirst和findAny
ble data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal">//前三個(gè)方法都是返回boolean類(lèi)型 boolean allMatchBool = menu.stream().allMatch(jsonObject -> jsonObject.getInt("price") < 10); boolean noneMatchBool = menu.stream().noneMatch(jsonObject -> jsonObject.getInt("price") < 10); boolean anyMatchBool = menu.stream().anyMatch(jsonObject -> jsonObject.getInt("price") < 10);上面?zhèn)€方法返回的都是boolean類(lèi)型,findFirst、findAny返回的都是元素。
//關(guān)于Optional,先不關(guān)心,總之是元素就對(duì)了 Optional<JSONObject> first = menu.stream().findFirst(); Optional<JSONObject> any = menu.stream().findAny();System.out.println(first.get().toString()); System.out.println(any.get().toString());//輸出 //{"price":"28","name":"宮保雞丁"} //{"price":"28","name":"宮保雞丁"}以上兩個(gè)方法,只要找到符合條件的數(shù)據(jù),流就提前結(jié)束了。為什么都是輸出第一個(gè)元素,卻要實(shí)現(xiàn)有兩個(gè)方法呢?因?yàn)椴⑿?#xff0c;findAny在并行方面限制會(huì)少一些。
reduce
最開(kāi)始的時(shí)候說(shuō)了,最終的返回值可以是元素集合,也可以是統(tǒng)計(jì)數(shù)據(jù)(或者說(shuō)歸納),比如說(shuō)元素求和。假設(shè)我們需要menu中所有食品各要一份需要花多少錢(qián)。
Optional<Integer> price = menu.stream()//List<JsonObject>.map(jsonObject -> jsonObject.getInt("price"))//先將元素轉(zhuǎn)成數(shù)字List<Integer>.reduce((x, y) -> x + y); System.out.println(price.get());max和min
這個(gè)好理解,就是最大值和最小值嘛。效果類(lèi)似于
.reduce(Integer::max) .reduce(Integer::min)常用流匯總
其中沒(méi)有展示sorted、count這個(gè)都好理解。至于collect這個(gè)后面講,用的比較多。
流的轉(zhuǎn)化
除了對(duì)象流(Stream)以外,還有一些類(lèi)型流,比如說(shuō) IntStream(以 IntStream 舉例,其他類(lèi)似)上面求和返回的是Optional對(duì)象,那可以直接返回Integer類(lèi)型嗎?
//使用映射方法mapToInt()就ok了 int price = menu.stream()//Stream.mapToInt(jsonObject -> jsonObject.getInt("price"))//IntStream.sum(); //類(lèi)型流轉(zhuǎn)化回對(duì)象流,可以使用boxed() IntStream intStream = menu.stream().mapToInt(jsonObject -> jsonObject.getInt("price")); Stream<Integer> boxed = intStream.boxed(); //當(dāng)然了IntStream中有很多int類(lèi)型操作的方法,就不一一舉例了,源碼打開(kāi)一看,見(jiàn)名知意收集器
前面講的常用的中間操作,返回值都是流,還有一些中斷操作,返回值都是Optional或者數(shù)值。可別忘了Stream最開(kāi)始的初衷是為了解決集合操作問(wèn)題。最終轉(zhuǎn)化成集合使用的中斷操作collect,參數(shù)是接口 Collector,里面有眾多轉(zhuǎn)化方法。
轉(zhuǎn)換成集合
最常用的莫非toList() 這個(gè)方法了,將返回結(jié)果變成List。
List<JSONObject> list = menu.stream().filter(jsonObject -> jsonObject.getInt("price") < 10).collect(Collectors.toList()); //當(dāng)然還有toSet()等等,觸類(lèi)旁通字符串拼接
比較常用,就是字符串鏈接了。使用joining()方法
String s = menu.stream().filter(jsonObject -> jsonObject.getInt("price") < 10).map(jsonObject -> jsonObject.getStr("name")).collect(Collectors.joining(","));分組
根據(jù)提供的屬性分組,使用 groupingBy() ,為了方便說(shuō)明,給上面各種食品一個(gè)type值:
List<JSONObject> menu = new ArrayList<>(); menu.add(new JSONObject().putOpt("name","宮保雞丁").putOpt("price","28").putOpt("type","good")); menu.add(new JSONObject().putOpt("name","魚(yú)香肉絲").putOpt("price","30").putOpt("type","good")); menu.add(new JSONObject().putOpt("name","肉夾饃").putOpt("price","6").putOpt("type","normal")); menu.add(new JSONObject().putOpt("name","煎餅").putOpt("price","6").putOpt("type","normal"));Map<String, List<JSONObject>> type = menu.stream().collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("type"))); System.out.println(type); //輸出 //{normal=[{"price":"6","name":"肉夾饃","type":"normal"}, {"price":"6","name":"煎餅","type":"normal"}], good=[{"price":"28","name":"宮保雞丁","type":"good"}, {"price":"30","name":"魚(yú)香肉絲","type":"good"}]}與分組類(lèi)似的還有一個(gè)方法 partitioningBy (),分區(qū),不過(guò)它的參數(shù)位于是boolean類(lèi)型。
總結(jié)
以上是生活随笔為你收集整理的stream distinct去重_再来看看Java的新特性——Stream流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一般性网络错误 请检查网络文档_如何编写
- 下一篇: 80070583类不存在_结合JVM源码