最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java Stream將集合轉(zhuǎn)換為一對(duì)一Map的方法詳解

 更新時(shí)間:2025年12月29日 08:42:36   作者:申城異鄉(xiāng)人  
在日常的開(kāi)發(fā)工作中,我們經(jīng)常使用到Java Stream,特別是Stream API中提供的Collectors.toList()收集器,但有些場(chǎng)景下,我們需要將集合轉(zhuǎn)換為Map,所以本文就給大家介紹了如何使用Java Stream將集合轉(zhuǎn)換為一對(duì)一Map,需要的朋友可以參考下

引言

在日常的開(kāi)發(fā)工作中,我們經(jīng)常使用到Java Stream,特別是Stream API中提供的Collectors.toList()收集器,但有些場(chǎng)景下,我們需要將集合轉(zhuǎn)換為Map,這時(shí)候就需要使用到Stream API中提供的另一個(gè)收集器:Collectors.toMap,它可以將流中的元素映射為鍵值對(duì),并收集到一個(gè)Map中。

1. 三種主要的重載方法

Collectors.toMap有3種重載方法,分別是:

1)兩個(gè)參數(shù)的重載方法(最簡(jiǎ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);
}

2)三個(gè)參數(shù)的重載方法(包含沖突處理)

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

3)四個(gè)參數(shù)的重載方法(指定Map實(shí)現(xiàn))

public static <T, K, U, M extends Map<K, U>>
   Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                            Function<? super T, ? extends U> valueMapper,
                            BinaryOperator<U> mergeFunction,
                            Supplier<M> mapSupplier) {
    BiConsumer<M, T> accumulator
            = (map, element) -> map.merge(keyMapper.apply(element),
                                          valueMapper.apply(element), mergeFunction);
    return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}

接下來(lái),我們結(jié)合使用示例詳細(xì)講解。

2. 使用示例

2.1 將對(duì)象的某些屬性轉(zhuǎn)換為Map

假設(shè)有一個(gè)城市列表,需要將其轉(zhuǎn)換為Map,其中Key為城市ID、Value為城市名稱,轉(zhuǎn)換方法如下所示:

@Getter
@Setter
public class City {
    private Integer cityId;

    private String cityName;

    public City(Integer cityId, String cityName) {
        this.cityId = cityId;
        this.cityName = cityName;
    }
}
List<City> cityList = Arrays.asList(
        new City(1, "北京"),
        new City(2, "上海"),
        new City(3, "廣州"),
        new City(4, "深圳")
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName));
System.out.println(cityMap);

輸出結(jié)果:

{1=北京, 2=上海, 3=廣州, 4=深圳}

2.2 將對(duì)象列表轉(zhuǎn)換為Map(ID -> 對(duì)象)

仍然使用上面的城市列表,需要將其轉(zhuǎn)換為Map,其中Key為城市ID、Value為城市對(duì)象,轉(zhuǎn)換方法如下所示:

List<City> cityList = Arrays.asList(
        new City(1, "北京"),
        new City(2, "上海"),
        new City(3, "廣州"),
        new City(4, "深圳")
);
Map<Integer, City> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, city -> city));
City city = cityMap.get(1);
System.out.println("城市ID: " + city.getCityId());
System.out.println("城市名稱: " + city.getCityName());

輸出結(jié)果如下所示:

城市ID: 1 城市名稱: 北京

上面的寫法等價(jià)于:

Map<Integer, City> cityMap = cityList.stream()
    	.collect(Collectors.toMap(City::getCityId, Function.identity()));

因?yàn)?code>Function.identity()內(nèi)部實(shí)現(xiàn)是下面這樣的:

static <T> Function<T, T> identity() {
    return t -> t;
}

2.3 鍵沖突處理

假設(shè)上面的城市列表中有一個(gè)ID重復(fù)的城市:

List<City> cityList = Arrays.asList(
        new City(1, "北京"),
        new City(2, "上海"),
        new City(3, "廣州"),
        new City(4, "深圳"),
        new City(4, "天津")
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName));
System.out.println("城市ID: 4, 城市名稱: " + cityMap.get(4));

此時(shí)運(yùn)行代碼,會(huì)拋出java.lang.IllegalStateException異常,如下圖所示:

有3種常見(jiàn)的鍵沖突處理方式,分別是保留舊值、使用新值和合并值,接下來(lái)一一講解。

1)方式一:保留舊值

Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName, (oldValue, newValue) -> oldValue));

輸出結(jié)果:

城市ID: 4, 城市名稱: 深圳

2)方式二:使用新值

Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName, (oldValue, newValue) -> newValue));

輸出結(jié)果:

城市ID: 4, 城市名稱: 天津

3)方式三:合并值

Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName, 
        		(oldValue, newValue) -> oldValue + ", " + newValue));

輸出結(jié)果:

城市ID: 4, 城市名稱: 深圳, 天津

2.4 數(shù)據(jù)分組聚合

假設(shè)有一個(gè)銷售記錄列表,需要將其轉(zhuǎn)換為Map,其中Key為銷售員、Value為該銷售員的總銷售額,轉(zhuǎn)換方法如下所示:

@Getter
@Setter
public class SalesRecord {
    private String salesPerson;

    private BigDecimal amount;

    public SalesRecord(String salesPerson, BigDecimal amount) {
        this.salesPerson = salesPerson;
        this.amount = amount;
    }
}
List<SalesRecord> salesRecordList = Arrays.asList(
        new SalesRecord("張三", new BigDecimal("1000")),
        new SalesRecord("李四", new BigDecimal("2000")),
        new SalesRecord("張三", new BigDecimal("980"))
);

Map<String, BigDecimal> salesRecordMap = salesRecordList.stream()
        .collect(Collectors.toMap(SalesRecord::getSalesPerson, SalesRecord::getAmount, BigDecimal::add));
System.out.println(salesRecordMap);

輸出結(jié)果:

{李四=2000, 張三=1980}

上面的例子是銷售額累加,也可以只取最小值:

Map<String, BigDecimal> salesRecordMap = salesRecordList.stream()
        .collect(Collectors.toMap(SalesRecord::getSalesPerson, SalesRecord::getAmount, BigDecimal::min));

此時(shí)的輸出結(jié)果:

{李四=2000, 張三=980}

或者只取最大值:

Map<String, BigDecimal> salesRecordMap = salesRecordList.stream()
        .collect(Collectors.toMap(SalesRecord::getSalesPerson, SalesRecord::getAmount, BigDecimal::max));

此時(shí)的輸出結(jié)果:

{李四=2000, 張三=1000}

2.5 指定Map實(shí)現(xiàn)

默認(rèn)情況下,Collectors.toMap是將結(jié)果收集到HashMap中,如果有需要,我們也可以指定成TreeMap或者LinkedHashMap。

如果想要保持插入順序,可以指定使用LinkedHashMap:

List<City> cityList = Arrays.asList(
        new City(2, "上海"),
        new City(1, "北京"),
        new City(4, "深圳"),
        new City(3, "廣州")
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName,
                (existing, replacement) -> existing, LinkedHashMap::new));
System.out.println(cityMap);

輸出結(jié)果:

{2=上海, 1=北京, 4=深圳, 3=廣州}

如果想要按鍵排序,可以指定使用TreeMap:

List<City> cityList = Arrays.asList(
        new City(2, "上海"),
        new City(1, "北京"),
        new City(4, "深圳"),
        new City(3, "廣州")
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName,
                (existing, replacement) -> existing, TreeMap::new));
System.out.println(cityMap);

輸出結(jié)果:

{1=北京, 2=上海, 3=廣州, 4=深圳}

3. 注意事項(xiàng)

3.1 空異常

如果valueMapper中取出的值有null值,會(huì)拋出java.lang.NullPointerException異常,如下示例:

List<City> cityList = Arrays.asList(
        new City(1, "北京"),
        new City(2, "上海"),
        new City(3, "廣州"),
        new City(4, "深圳"),
        new City(5, null)
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName));
System.out.println(cityMap);

運(yùn)行以上代碼會(huì)拋出異常,如下圖所示:

有兩種解決方案,第一種解決方案是過(guò)濾null值:

Map<Integer, String> cityMap = cityList.stream()
        .filter(city -> city.getCityName() != null)
        .collect(Collectors.toMap(City::getCityId, City::getCityName));

第二種解決方案是提供默認(rèn)值:

Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId,
                city -> Optional.ofNullable(city.getCityName()).orElse("未知")));

3.2 鍵重復(fù)異常

如果出現(xiàn)重復(fù)鍵,且沒(méi)有提供mergeFunction參數(shù),會(huì)拋出java.lang.IllegalStateException異常,如下示例:

List<City> cityList = Arrays.asList(
        new City(1, "北京"),
        new City(2, "上海"),
        new City(3, "廣州"),
        new City(4, "深圳"),
        new City(4, "天津")
);
Map<Integer, String> cityMap = cityList.stream()
        .collect(Collectors.toMap(City::getCityId, City::getCityName));
System.out.println(cityMap);

運(yùn)行以上代碼會(huì)拋出異常,如下圖所示:

解決方案見(jiàn)本篇文章2.3 鍵沖突處理部分。

4. 總結(jié)

Collectors.toMap是Stream API中提供的一個(gè)非常方便的收集器,它可以將流中的元素映射為鍵值對(duì),并收集到一個(gè)Map中。

它適用于一對(duì)一映射的場(chǎng)景,但在使用時(shí),要注意避免java.lang.NullPointerException異常和

java.lang.IllegalStateException異常。

以上就是使用Java Stream將集合轉(zhuǎn)換為一對(duì)一Map的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Stream集合轉(zhuǎn)一對(duì)一Map的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringMVC獲取HTTP中元素的實(shí)現(xiàn)示例

    SpringMVC獲取HTTP中元素的實(shí)現(xiàn)示例

    本文主要介紹了SpringMVC獲取HTTP中的元素,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • ReentrantrantLock底層實(shí)現(xiàn)原理及分析

    ReentrantrantLock底層實(shí)現(xiàn)原理及分析

    本文詳細(xì)介紹了Java并發(fā)包中ReentrantLock的實(shí)現(xiàn)原理,包括非公平鎖和公平鎖的加鎖和解鎖機(jī)制,以及可重入和可打斷特性,同時(shí),還介紹了條件變量的實(shí)現(xiàn)原理,通過(guò)await和signal方法來(lái)管理線程間的等待和喚醒
    2026-03-03
  • Spring Security自定義認(rèn)證器的實(shí)現(xiàn)代碼

    Spring Security自定義認(rèn)證器的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Spring Security自定義認(rèn)證器的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Spring?Boot?Admin?添加報(bào)警提醒和登錄驗(yàn)證功能的具體實(shí)現(xiàn)

    Spring?Boot?Admin?添加報(bào)警提醒和登錄驗(yàn)證功能的具體實(shí)現(xiàn)

    報(bào)警提醒功能是基于郵箱實(shí)現(xiàn)的,當(dāng)然也可以使用其他的提醒功能,如釘釘或飛書機(jī)器人提醒也是可以的,但郵箱報(bào)警功能的實(shí)現(xiàn)成本最低,所以本文我們就來(lái)看郵箱的報(bào)警提醒功能的具體實(shí)現(xiàn)
    2022-01-01
  • SpringMVC使用@PathVariable接收參數(shù)過(guò)程解析

    SpringMVC使用@PathVariable接收參數(shù)過(guò)程解析

    這篇文章主要介紹了SpringMVC使用@PathVariable接收參數(shù)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java實(shí)現(xiàn)圖片模糊效果詳解

    Java實(shí)現(xiàn)圖片模糊效果詳解

    圖片模糊是圖像處理中的一種常見(jiàn)效果,它通過(guò)平均周圍像素的顏色來(lái)使圖像變得模糊,下面我們來(lái)看看如何使用Swing庫(kù)實(shí)現(xiàn)圖片模糊效果吧
    2025-02-02
  • Java聊天室之實(shí)現(xiàn)聊天室服務(wù)端功能

    Java聊天室之實(shí)現(xiàn)聊天室服務(wù)端功能

    這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易聊天室之實(shí)現(xiàn)聊天室服務(wù)端功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下
    2022-10-10
  • SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤

    SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤

    這篇文章主要介紹了SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • java中Collections.sort排序詳解

    java中Collections.sort排序詳解

    這篇文章主要介紹了java中Collections.sort排序詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • java jvm的知識(shí)詳細(xì)介紹

    java jvm的知識(shí)詳細(xì)介紹

    這篇文章主要介紹了java jvm的知識(shí)詳細(xì)介紹的相關(guān)資料,這里對(duì)java jvm中的堆內(nèi)存和棧內(nèi)存等基礎(chǔ)知識(shí)做了詳細(xì)介紹,需要的朋友可以參考下
    2016-11-11

最新評(píng)論

德惠市| 龙岩市| 伽师县| 建昌县| 邵阳县| 屏南县| 寿宁县| 三河市| 邳州市| 梅河口市| 曲麻莱县| 甘洛县| 左云县| 临沧市| 察隅县| 金阳县| 天柱县| 大英县| 霍城县| 五常市| 永登县| 四平市| 阜平县| 清苑县| 绍兴县| 临洮县| 汉中市| 永昌县| 金秀| 页游| 建宁县| 白银市| 梁山县| 团风县| 安达市| 来宾市| 华安县| 剑河县| 玛纳斯县| 楚雄市| 霍邱县|