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 、使用合并函数可以配合排序函数 ,根据排序规则正序 、倒序 ,取每组重复数据中最近或最远的一条数据 ,用来处理适当的业务 。(上面没有举例 ,自行验证)
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!