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

Java?Stream?的?Collectors.toMap高級應用與最佳實踐

 更新時間:2025年08月04日 16:48:47   作者:潛意識Java  
文章講解Java?Stream?API中Collectors.toMap的使用,涵蓋基礎(chǔ)語法、鍵沖突處理、自定義Map類型、null值安全、復雜值轉(zhuǎn)換及性能優(yōu)化等場景,本文將從基礎(chǔ)用法入手,逐步深入探討其高級應用與最佳實踐,感興趣的朋友一起看看吧

在 Java Stream API 中,Collectors.toMap 是一個強大的終端操作,用于將流中的元素轉(zhuǎn)換為 Map 結(jié)構(gòu)。雖然其基礎(chǔ)用法較為直觀,但在處理復雜場景(如鍵沖突、值轉(zhuǎn)換、類型安全等)時,需要掌握一些進階技巧。本文將從基礎(chǔ)用法入手,逐步深入探討其高級應用與最佳實踐。

一、基礎(chǔ)用法回顧

Collectors.toMap 有三種重載形式:

// 基礎(chǔ)形式:keyMapper 和 valueMapper
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(
    Function<? super T, ? extends K> keyMapper,
    Function<? super T, ? extends U> valueMapper)
// 帶合并函數(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)
// 帶合并函數(shù)和 Map 工廠的形式:指定 Map 實現(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)

二、處理鍵沖突

當流中的元素生成重復鍵時,必須提供合并函數(shù),否則會拋出 IllegalStateException。

1. 保留最后出現(xiàn)的元素

class Person {
    private String id;
    private String name;
    // 構(gòu)造器、getter 略
}
List<Person> people = Arrays.asList(
    new Person("1", "Alice"),
    new Person("2", "Bob"),
    new Person("2", "Charlie")  // 重復鍵
);
// 保留最后出現(xiàn)的值
Map<String, String> idToName = people.stream()
    .collect(Collectors.toMap(
        Person::getId,          // key:ID
        Person::getName,        // value:姓名
        (existing, replacement) -> replacement  // 合并函數(shù):保留新值
    ));
// 輸出:{1=Alice, 2=Charlie}

2. 合并值

// 將重復鍵的值合并為列表
Map<String, List<String>> idToNames = people.stream()
    .collect(Collectors.toMap(
        Person::getId,
        p -> Collections.singletonList(p.getName()),  // 單個值轉(zhuǎn)為列表
        (list1, list2) -> {
            List<String> merged = new ArrayList<>(list1);
            merged.addAll(list2);
            return merged;
        }  // 合并函數(shù):合并兩個列表
    ));
// 輸出:{1=[Alice], 2=[Bob, Charlie]}

三、自定義 Map 實現(xiàn)類型

默認情況下,toMap 返回 HashMap,可通過 mapSupplier 參數(shù)指定其他實現(xiàn)。

1. 使用 LinkedHashMap 保持插入順序

Map<String, String> orderedMap = people.stream()
    .collect(Collectors.toMap(
        Person::getId,
        Person::getName,
        (existing, replacement) -> replacement,  // 合并函數(shù)
        LinkedHashMap::new  // 指定 Map 實現(xiàn)
    ));

2. 使用 TreeMap 按鍵排序

Map<Integer, String> sortedMap = Stream.of(
    new AbstractMap.SimpleEntry<>(3, "C"),
    new AbstractMap.SimpleEntry<>(1, "A"),
    new AbstractMap.SimpleEntry<>(2, "B")
).collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (existing, replacement) -> existing,  // 合并函數(shù)(本例不會觸發(fā))
    TreeMap::new  // 指定 TreeMap
));
// 輸出:{1=A, 2=B, 3=C}(按鍵排序)

四、處理 null 值

Java 8 的 toMap 不允許鍵或值為 null,否則會拋出 NullPointerException。Java 9+ 提供了更寬容的實現(xiàn),但在 Java 8 中需手動處理。

1. 過濾 null 值

Map<String, Integer> lengthMap = Stream.of("apple", null, "banana")
    .filter(Objects::nonNull)  // 過濾 null 元素
    .collect(Collectors.toMap(
        Function.identity(),
        String::length
    ));

2. 替換 null 值

Map<String, String> safeMap = people.stream()
    .collect(Collectors.toMap(
        Person::getId,
        p -> p.getName() != null ? p.getName() : "Unknown",  // 替換 null 值
        (existing, replacement) -> replacement
    ));

五、復雜值類型轉(zhuǎn)換

1. 收集到自定義對象

class UserStats {
    private int loginCount;
    private LocalDate lastLogin;
    public UserStats(int count, LocalDate date) {
        this.loginCount = count;
        this.lastLogin = date;
    }
    // getters, setters 略
}
Map<String, UserStats> userStatsMap = userActivityStream
    .collect(Collectors.toMap(
        UserActivity::getUserId,  // 鍵:用戶ID
        activity -> new UserStats(  // 值:自定義對象
            1,                      // 初始登錄次數(shù)
            activity.getLoginTime() // 最后登錄時間
        ),
        (existing, newActivity) -> {  // 合并函數(shù)
            existing.setLoginCount(existing.getLoginCount() + 1);
            existing.setLastLogin(max(existing.getLastLogin(), newActivity.getLastLogin()));
            return existing;
        }
    ));

2. 與 groupingBy 結(jié)合

// 按部門分組,統(tǒng)計每個部門的員工姓名列表
Map<String, List<String>> employeesByDepartment = people.stream()
    .collect(Collectors.groupingBy(
        Person::getDepartment,
        Collectors.mapping(Person::getName, Collectors.toList())
    ));
// 使用 toMap 實現(xiàn)相同功能
Map<String, List<String>> employeesByDept = people.stream()
    .collect(Collectors.toMap(
        Person::getDepartment,
        p -> Collections.singletonList(p.getName()),
        (list1, list2) -> {
            List<String> merged = new ArrayList<>(list1);
            merged.addAll(list2);
            return merged;
        }
    ));

六、處理流元素為 Map.Entry

當流元素本身就是 Map.Entry 時,可使用 Function.identity() 簡化轉(zhuǎn)換。

List<Map.Entry<String, Integer>> entries = Arrays.asList(
    new AbstractMap.SimpleEntry<>("A", 1),
    new AbstractMap.SimpleEntry<>("B", 2),
    new AbstractMap.SimpleEntry<>("C", 3)
);
// 將 Entry 流轉(zhuǎn)換為 Map
Map<String, Integer> resultMap = entries.stream()
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (existing, replacement) -> replacement  // 處理鍵沖突
    ));

七、性能優(yōu)化與注意事項

避免重復計算

// 低效:每次調(diào)用都計算 length()
Map<String, Integer> map = words.stream()
    .collect(Collectors.toMap(
        Function.identity(),
        String::length,
        (e, r) -> r
    ));
// 高效:使用 mapToEntry 預先計算
Map<String, Integer> optimizedMap = words.stream()
    .map(word -> new AbstractMap.SimpleEntry<>(word, word.length()))
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (e, r) -> r
    ));
  • 處理大型數(shù)據(jù)集
    • 并行流中使用 toConcurrentMap 替代 toMap
    • 確保合并函數(shù)線程安全
  • 鍵的唯一性
    • 若流中可能存在重復鍵,必須提供合并函數(shù)
    • 使用 Collectors.toUnmodifiableMap(Java 10+)創(chuàng)建不可變 Map

八、總結(jié)與最佳實踐

基礎(chǔ)用法

Map<KeyType, ValueType> map = stream.collect(
    Collectors.toMap(
        element -> element.getKey(),
        element -> element.getValue()
    )
);

處理鍵沖突

.collect(Collectors.toMap(
    keyMapper,
    valueMapper,
    (existing, replacement) -> replacement  // 保留新值
))

指定 Map 類型

.collect(Collectors.toMap(
    keyMapper,
    valueMapper,
    mergeFunction,
    LinkedHashMap::new  // 保持插入順序
))

安全處理 null

.filter(Objects::nonNull)  // 過濾 null 元素
.collect(Collectors.toMap(
    keyMapper,
    value -> value != null ? value : defaultValue
))

通過靈活運用 Collectors.toMap 的各種重載形式和參數(shù)組合,可以高效處理從簡單到復雜的各種數(shù)據(jù)轉(zhuǎn)換需求,使代碼更加簡潔、健壯。

到此這篇關(guān)于深入掌握 Java Stream 的 Collectors.toMap 進階應用的文章就介紹到這了,更多相關(guān)Java Stream 的 Collectors.toMap用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA設計模式中的策略模式你了解嗎

    JAVA設計模式中的策略模式你了解嗎

    這篇文章主要為大家詳細介紹了JAVA設計模式中的策略模式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Java線程間的通信方式詳解

    Java線程間的通信方式詳解

    這篇文章主要為大家詳細介紹了Java線程間的通信方式,以代碼結(jié)合文字的方式來討論線程間的通信,感興趣的朋友可以參考一下
    2016-05-05
  • Java JVM類加載器知識總結(jié)

    Java JVM類加載器知識總結(jié)

    本文介紹Java虛擬機(JVM)中的類加載器,包括類加載器的概述、作用、基本流程及JVM類加載器的類型和層次,文章探討了類加載的實際應用和優(yōu)化,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • 詳解Java生成PDF文檔方法

    詳解Java生成PDF文檔方法

    這篇文章主要介紹了Java生成PDF文檔方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • java8 Instant 時間及轉(zhuǎn)換操作

    java8 Instant 時間及轉(zhuǎn)換操作

    這篇文章主要介紹了java8 Instant 時間及轉(zhuǎn)換操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot如何啟動自動加載自定義模塊yml文件(PropertySourceFactory)

    SpringBoot如何啟動自動加載自定義模塊yml文件(PropertySourceFactory)

    這篇文章主要介紹了SpringBoot如何啟動自動加載自定義模塊yml文件(PropertySourceFactory),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • SpringBoot+layui實現(xiàn)文件上傳功能

    SpringBoot+layui實現(xiàn)文件上傳功能

    Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發(fā)過程。這篇文章主要介紹了SpringBoot+layui實現(xiàn)文件上傳,需要的朋友可以參考下
    2018-09-09
  • Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(動力節(jié)點Java學院整理)

    Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(動力節(jié)點Java學院整理)

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之棧,棧是先進后出的數(shù)據(jù)的結(jié)構(gòu),本文通過文字說明與實例代碼相結(jié)合的形式給大家介紹的非常詳細,需要的朋友跟著小編一起學習吧
    2017-04-04
  • MyBatis寫入Json字段以及Json字段轉(zhuǎn)對象示例詳解

    MyBatis寫入Json字段以及Json字段轉(zhuǎn)對象示例詳解

    這篇文章主要給大家介紹了關(guān)于MyBatis寫入Json字段以及Json字段轉(zhuǎn)對象的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Java線程的調(diào)度與優(yōu)先級詳解

    Java線程的調(diào)度與優(yōu)先級詳解

    這篇文章主要為大家詳細介紹了Java線程的調(diào)度與優(yōu)先級,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評論

彰武县| 柞水县| 临江市| 武宣县| 乐至县| 耒阳市| 柞水县| 高台县| 南岸区| 澄江县| 德化县| 郑州市| 新巴尔虎左旗| 礼泉县| 万盛区| 于都县| 扎兰屯市| 女性| 博湖县| 铅山县| 安陆市| 庄浪县| 信丰县| 无为县| 西平县| 南丹县| 南昌市| 潜山县| 苗栗市| 洛南县| 孟津县| 平罗县| 临夏县| 白玉县| 无锡市| 五寨县| 调兵山市| 米林县| 平阳县| 饶平县| 关岭|