第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

求助,關(guān)于java8 Collectors的groupingBy和mapping

求助,關(guān)于java8 Collectors的groupingBy和mapping

犯罪嫌疑人X 2019-01-17 01:57:46
問(wèn)題描述 小弟嘗試將一段如下json讀到一個(gè)Map<String, List<String>>中,map 的key為condName,map的value為condValue 現(xiàn)在用stream結(jié)合Collectors的groupingBy和toList方法,將List<Condition>轉(zhuǎn)成了Map<String, List<Condition>> 然后嘗試通過(guò)mapping方法將List<Condition>映射為L(zhǎng)ist<String>時(shí)發(fā)現(xiàn)無(wú)從下手。。。幾次嘗試后得到了一個(gè)Map<String, List<List<String>>>,多了一層List 想去掉這一層List,如果再遍歷一遍又感覺(jué)不太優(yōu)雅 求助各位有什么思路嗎,最好是通過(guò)mapping一次得到想要的結(jié)果 不勝感激! 問(wèn)題出現(xiàn)的環(huán)境背景及自己嘗試過(guò)哪些方法 相關(guān)代碼 { "condition": [ { "condName": "name1", "condValue": [ "val11", "val12" ] }, { "condName": "name2", "condValue": [ "val21" ] }, { "condName": "name3", "condValue": [ "val31", "val32", "val33" ] } ], "total": 3 } @Data public class Request { private List<Condition> condition; private Long total; } @Data public class Condition { private String condName; private List<String> condValue; } 轉(zhuǎn)換方法(讀取json和轉(zhuǎn)成Request對(duì)象的代碼省略。。。): String json = getContent(); try { List<Condition> conditions = deseriliaze(json).getCondition(); Map<String, List<Condition>> map1 = conditions.stream().collect(Collectors.groupingBy(Condition::getCondName)); Map<String, List<List<String>>> map2 = conditions.stream().collect(Collectors.groupingBy(Condition::getCondName, Collectors.mapping(Condition::getCondValue, Collectors.toList()))); } catch (Exception e) { e.printStackTrace(); } 你期待的結(jié)果是什么?實(shí)際看到的錯(cuò)誤信息又是什么? map1: {name3=[Condition(condName=name3, condValue=[val31, val32, val33])], name2=[Condition(condName=name2, condValue=[val21])], name1=[Condition(condName=name1, condValue=[val11, val12])]} map2: {name3=[[val31, val32, val33]], name2=[[val21]], name1=[[val11, val12]]}
查看完整描述

1 回答

?
BIG陽(yáng)

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個(gè)贊

回答這個(gè)問(wèn)題的話,我們可以先來(lái)看看為啥會(huì)出現(xiàn)Map<String, List<List<String>>>的結(jié)果,這要從Collectors.groupingBy的設(shè)計(jì)語(yǔ)義來(lái)說(shuō)了,它代表把流的數(shù)據(jù)按照一定規(guī)則進(jìn)行歸類分組,并要求提供同一組的數(shù)據(jù)怎么進(jìn)行收集的方法,所以這就是Collectors.groupingBy兩個(gè)參數(shù)的含義

那題主第一個(gè)參數(shù)寫的是Condition::getCondName,代表流的Condition按照其condName屬性進(jìn)行分組,分組之后,同一組的Condition如何處理,這里題主用的Collectors.mapping(Condition::getCondValue, Collectors.toList())),mapping代表映射轉(zhuǎn)換,這里有點(diǎn)類似分組,Collectors.mapping第一個(gè)參數(shù)把流的Condition轉(zhuǎn)化為List<String>,此時(shí)流里就是List<String>,再經(jīng)過(guò)第二個(gè)參數(shù)Collectors.toList(),哦豁,當(dāng)然最后結(jié)果就是List<List<String>>

這里題主得不到答案的原因就是Collectors.mapping的第二個(gè)參數(shù)沒(méi)有寫對(duì),我這里想到三種方式
第一種:還是用Collectors.mapping,類似題主提到的再遍歷一遍,哈哈

Map<String, List<String>> collect = conditions.stream()
                .collect(Collectors.groupingBy(Condition::getCondName,
                                Collectors.mapping(Condition::getCondValue,
                                        Collectors.collectingAndThen(Collectors.toList(), lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())))));

這里Collectors.mapping的第二個(gè)參數(shù)用了Collectors.collectingAndThen,從名字就看得出來(lái),收集好了之后再做什么事...第一個(gè)參數(shù)當(dāng)然還是按照Collectors.toList(),收集到之后,第二個(gè)參數(shù)再把List遍歷一次,壓平后再組成List

emmm,我也不太喜歡這種,不過(guò)只是引出了哈collectingAndThen,說(shuō)不定以后題主可以用到

第二種:也還是用Collectors.mapping,不過(guò)這次第二個(gè)參數(shù)用Collectors.reducing

Map<String, List<String>> collect2 = conditions.stream()
                .collect(Collectors.groupingBy(Condition::getCondName, 
                        Collectors.mapping(Condition::getCondValue, 
                                Collectors.reducing(new ArrayList<>(), (l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(Collectors.toList())))));

這里的Collectors.reducing就是數(shù)據(jù)的聚合,正好也符合當(dāng)前的場(chǎng)景,當(dāng)流里的數(shù)據(jù)由Condition轉(zhuǎn)化為List<String>時(shí),我們就是要找到一種合并不同List<String>的方法,所以這里用到這個(gè)聚合方法Collectors.reducing,第一個(gè)參數(shù)是起始值,第二個(gè)參數(shù)代表怎么合并兩個(gè)list

第二個(gè)方法要好一點(diǎn),不過(guò)這里我還想到第三個(gè)方法

第三種:不用Collectors.groupingBy,而采用Collectors.toMap

Map<String, List<String>> collect1 = conditions.stream().collect(
                Collectors.toMap(Condition::getCondName, Condition::getCondValue, (c1, c2) -> Stream.concat(c1.stream(), c2.stream()).collect(Collectors.toList())));

第三種方式感覺(jué)要比前兩種簡(jiǎn)單點(diǎn),但是這是巧用了哈toMap方法,toMap方法一般使用在數(shù)據(jù)能夠有一種一對(duì)一的關(guān)系時(shí)才用,大多數(shù)的時(shí)候我們一般也只使用兩個(gè)參數(shù)的方法,即傳入怎么獲取mapkey和怎么獲取mapvalue的兩個(gè)Function,因?yàn)橐话闱闆r下,業(yè)務(wù)上可以保證數(shù)據(jù)是具有一對(duì)一的關(guān)系的,如果只是調(diào)用兩參方法,但是實(shí)際使用過(guò)程中,確實(shí)出現(xiàn)了一對(duì)多的情況,那么這時(shí)候調(diào)用toMap兩參方法是會(huì)報(bào)錯(cuò)的,因此就有了toMap這個(gè)三參方法,第三個(gè)參數(shù)代表怎么合并同一個(gè)keyvalue值,所以到了這里就跟第二種方法的思路差不多了,合并兩個(gè)集合即可

以上就是我的回答,僅供參考

對(duì)了,再加一點(diǎn),我一般是不太喜歡在流里寫過(guò)長(zhǎng)的lambda表達(dá)式的,因?yàn)榱骼锸且w現(xiàn)當(dāng)前流程的,不是爛七八糟的都往里噻,所以第三種方式,最后的集合合并,最好還是寫成一個(gè)BinaryOperator,畢竟現(xiàn)在方法也可以是一種參數(shù)或者屬性了嘛

public static final BinaryOperator<List<String>> listMergeMethod = (l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(Collectors.toList());
Map<String, List<String>> collect1 = conditions.stream().collect(
                Collectors.toMap(Condition::getCondName, Condition::getCondValue, listMergeMethod));

這樣我感覺(jué)要順點(diǎn)。。。

查看完整回答
1 反對(duì) 回復(fù) 2019-02-12
  • 1 回答
  • 0 關(guān)注
  • 9182 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)