bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

Collectors.toMap的問(wèn)題是什么

這篇文章給大家介紹Collectors.toMap的問(wèn)題是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

創(chuàng)新互聯(lián)長(zhǎng)期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為永修企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、網(wǎng)站制作,永修網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

概述

??雖然JDK9.0已經(jīng)出來(lái)了,不過(guò)我們系統(tǒng)最近才開(kāi)始全面引入JDK1.8,JDK1.8也已經(jīng)出來(lái)了好久了,各方面都挺穩(wěn)定的。最近在使用lambda表達(dá)式的Collectors.toMap方法時(shí)就遇到了一個(gè)問(wèn)題。
大致源碼如下:

public class Test {
    public static void main(String[] args) {
        // initMemberList為獲取數(shù)據(jù)的方法
        List<Member> list = Test.initMemberList();
        Map<String, String> memberMap = list.stream().collect(Collectors.toMap(Member::getId, Member::getImgPath));
        System.out.println(memberMap);
    }
}

class Member {
    private String id;
    private String imgPath;

    // get set省略
}

運(yùn)行程序,直接提示:

Exception in thread "main" java.lang.NullPointerException
    at java.util.HashMap.merge(HashMap.java:1224)
    at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at com.jdk.test.Test.main(Test.java:13)

??想來(lái)想去,一開(kāi)始一直沒(méi)想明白為什么會(huì)為空指針呢,因?yàn)閘ist是不可能為null的,無(wú)奈后來(lái)拿著java.util.HashMap.merge加NullPointerException異常上網(wǎng)搜索了一下。原來(lái)是由于在由對(duì)象轉(zhuǎn)為Map的時(shí)候,轉(zhuǎn)為map的value是null導(dǎo)致的。大概如下:

public static List<Member> initMemberList() {
        Member member1 = new Member();
        member1.setId("id_1");
        member1.setImgPath("http://www.baidu.com");
        // 這里有一個(gè)null導(dǎo)致的
        Member member2 = new Member();
        member2.setId("id_2");
        member2.setImgPath(null);

        List<Member> list = new ArrayList<>();
        list.add(member1);
        list.add(member2);
        return list;
    }

大致看了下源碼,原來(lái)Collectors.toMap底層是基于Map.merge方法來(lái)實(shí)現(xiàn)的,而merge中value是不能為null的,如果為null,就會(huì)拋出空指針異常,原來(lái)問(wèn)題是這樣的。

Collectors.toMap() internally uses Map.merge() to add mappings to the map. Map.merge() is spec'd not to allow null values, regardless of whether the underlying Map supports null values. This could probably use some clarification in the Collectors.toMap() specifications.

看了下,在openJDK的bug列表里還有這個(gè)呢:JDK-8148463,不知道這到底算不算bug呢。地址:Collectors.toMap fails on null values

問(wèn)題歸問(wèn)題,我們還是需要通過(guò)其他的方式解決的。

解決方式1

原來(lái)for循環(huán)的方式,亦或是forEach的方式:

Map<String, String> memberMap = new HashMap<>();
list.forEach((answer) -> memberMap.put(answer.getId(), answer.getImgPath()));
System.out.println(memberMap);

Map<String, String> memberMap = new HashMap<>();
for (Member member : list) {
    memberMap.put(member.getId(), member.getImgPath());
}

解決方式2

使用stream的collect的重載方法:

Map<String, String> memberMap = list.stream().collect(HashMap::new, (m,v)->
    m.put(v.getId(), v.getImgPath()),HashMap::putAll);
System.out.println(memberMap);

解決方式3

繼承Collector,手動(dòng)實(shí)現(xiàn)toMap方法,然后調(diào)用我們自己封裝的toMap方法就可以了。有關(guān)實(shí)現(xiàn)Collector,可參考:JDK8 Stream API中Collectors中toMap方法的問(wèn)題以及解決方案

??其實(shí)不管這是不是bug,說(shuō)到底,還是JDK1.8的lambda表達(dá)式用的太少,了解的太少導(dǎo)致的問(wèn)題。所以說(shuō)還是應(yīng)該多去使用新技術(shù),多踩坑。

stackoverflow地址:# Java 8 NullPointerException in Collectors.toMap

后記

使用Collector.toMap又發(fā)現(xiàn)了一個(gè)問(wèn)題,Map中的key不能重復(fù),如果重復(fù)的話,會(huì)拋出異常:

public static List<Member> initMemberList() {
    Member member1 = new Member();
    member1.setId("id_1");
    member1.setImgPath("http://www.google.com");

    Member member2 = new Member();
    member2.setId("id_1");
    member2.setImgPath("http://www.baidu.com");

    List<Member> list = new ArrayList<>();
    list.add(member1);
    list.add(member2);
    return list;
}

以上代碼,運(yùn)行時(shí),提示錯(cuò)誤:

Exception in thread "main" java.lang.IllegalStateException: Duplicate key http://www.google.com
    at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
    at java.util.HashMap.merge(HashMap.java:1253)
    at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at com.jdk.test.Test.main(Test.java:13)

通過(guò)查看Collectors.toMap的代碼及注釋我們會(huì)發(fā)現(xiàn):

public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper) {
    return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}

If the mapped keys contains duplicates (according to Object#equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.

??所以說(shuō)呢,我們使用的Collectors.toMap的方法是不支持key重復(fù)的,并且如果有重復(fù)的時(shí)候,建議我們使用toMap(Function, Function, BinaryOperator) 方法來(lái)替換使用,并且我們還可以定義當(dāng)key重復(fù)的時(shí)候,是使用舊的數(shù)據(jù)還是使用新的數(shù)據(jù)呢,除了選擇使用新舊數(shù)據(jù),當(dāng)然也可以做一些額外的操作,但該方法還是會(huì)有value為null的問(wèn)題哦
即:

Map<String, String> memberMap = list.stream().collect(Collectors.toMap(Member::getId, Member::getImgPath,
(oldValue,newValue) -> oldValue));
System.out.println(memberMap);

同樣,在openJDK的bug列表里自然也少不了這個(gè)小bug:JDK-8040892
Incorrect message in Exception thrown by Collectors.toMap(Function,Function)

不過(guò),在JDK9里這個(gè)bug應(yīng)該是被修復(fù)了的:JDK-8173464
Wrong exception message when collecting a stream to a map

Pallavi Sonal added a comment - 2017-01-27 00:42
This has been fixed in JDK 9 with JDK-8040892.
In JDK8 versions, it throws the wrong message i.e. instead of Duplicate key <KEY>, it shows Duplicate key <VALUE>.

??再多說(shuō)一句,toMap方法還有一個(gè)重載方法,是可以指定一個(gè)Map的具體實(shí)現(xiàn),該方法或許有時(shí)候我們會(huì)用到呢。

Map<String, String> memberMap = list.stream().collect(Collectors.toMap(Member::getId, Member::getImgPath,
    (oldValue,newValue) -> oldValue, HashMap::new));
System.out.println(memberMap);

關(guān)于Collectors.toMap的問(wèn)題是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

當(dāng)前標(biāo)題:Collectors.toMap的問(wèn)題是什么
當(dāng)前鏈接:http://vcdvsql.cn/article46/iigihg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)網(wǎng)站設(shè)計(jì)公司外貿(mào)建站全網(wǎng)營(yíng)銷推廣網(wǎng)站收錄網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)