Java8 Stream流Collectors.toMap当key重复时报异常(IllegalStateException)

一、问题

在使用Collectors.toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper)(两个参数的)时,如果 key 有重复,则会报异常(IllegalStateException)。

 

二、分析

Collectors.toMap()是有三个重载方法(2个参数,3个参数,4个参数),如下所示:

keyMapper:Key 的映射函数

valueMapper:Value 的映射函数

mergeFunction:当 Key 冲突时,调用的合并方法

mapSupplier:Map 构造器,在需要返回特定的 Map 时使用

1、toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
2、toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction);
3、toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);

①第一个,如果key冲突了,会默认抛出异常

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);
}

②第二个,如果key冲突了,可以按照指定的要求进行合并(取第一个还是最后一个)

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);
}

③第三个可以自定义异常方法和 Map 类型

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);
}

举例如下:

三、解决方法

避免出现重复时报异常,建议选用第二个带3个参数的 toMap 方法(一般取前面value的值,或者取后面放入的 value 值则覆盖先前的 value 值)。

1、选用重复 key 中第一个 value 值

Map<String, Object> result = list.stream().flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(m -> m.getKey(), m -> m.getValue(), (v1, v2) -> v1));

2、选用重复 key 中最后一个 value 值 (若重复 key 元素有2个则取第二元素的 value,若有3个则取第三个的 value,…)

Map<String, Object> result = list.stream().flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(m -> m.getKey(), m -> m.getValue(), (v1, v2) -> v2));

3、指定取哪个value值或哪种类型的value值(具体的实践根据具体的业务来操作数据即可)

4、直接返回一个给定的默认值

四、注意事项

1、key 不能有重复,如果重复则需要使用合并函数取默认值,否则会报错,因为 Map 的 key 不能重复。 2、合并函数有两个参数,第一个参数是重复数据中的第一个元素,第二个参数是重复数据中的最后一个元素,可以用来返回默认值。 3、使用合并函数可以配合排序函数,根据排序规则正序、倒序,取每组重复数据中最近或最远的一条数据,用来处理适当的业务。(上面没有举例,自行验证)

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 8的Collectors.toMap方法中,默认情况下,如果出现重复key,会抛出IllegalStateException异常。这意味着如果集合中有重复key,无法直接使用toMap方法。 为了解决这个问题,可以在toMap方法中传入一个合并函数,以决定如何处理重复key。例如,可以使用 (k1,k2) -> k1 来设置,如果有重复key,则保留key1,舍弃key2。这样就可以在处理重复key时避免异常的抛出。 此外,在Collectors.toMap方法的源代码中,可以看到第一个函数签名的注释说明了如果出现key冲突,会默认抛出异常。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ListToMapDuplicateKey.java](https://download.csdn.net/download/snxkxk/12321923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【开发问题系列】Collectors.toMap出现重复key问题](https://blog.csdn.net/qyj19920704/article/details/124607834)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java8 StreamCollectors.toMapkey重复时报异常IllegalStateException)](https://blog.csdn.net/davis_23/article/details/129175724)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值