Java8 Collectors.toMap的坑

  • 更新时间:2022-06-11 07:35:58
  • 编辑:麴月玲
给寻找Java相关教程的朋友们精选了java8相关的编程文章,网友魏惠娅根据主题投稿了本篇教程内容,涉及到Java8、Collectors.toMap、Java8 Collectors.toMap相关内容,已被898网友关注,如果对知识点想更进一步了解可以在下方电子资料中获取。
Java8编程入门官方教程
Java8编程入门官方教程
  • 大小:233 MB
  • 发布人:冯和泽
  • 下载:Java8

Java8 Collectors.toMap

按照常规思维,往一个map里put一个已经存在的key,会把原有的key对应的value值覆盖,然而通过一次线上问题,发现Java8中的Collectors.toMap反其道而行之,它默认给抛异常,抛异常...

线上业务代码出现Duplicate Key的异常,影响了业务逻辑,查看抛出异常部分的代码,类似以下写法:

Map<Integer, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));

然后list里面有id相同的对象,结果转map的时候居然直接抛异常了。。查源码发现toMap方法默认使用了个throwingMerger

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);
}
 
 
private static <T> BinaryOperator<T> throwingMerger() {
  return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}

那么这个throwingMerger是哪里用的呢?

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

这里传进去的是HashMap,所以最终走的是HashMap的merge方法。merge方法里面有这么一段代码:

if (old != null) {
  V v;
  if (old.value != null)
    v = remappingFunction.apply(old.value, value);
  else
    v = value;
  if (v != null) {
    old.value = v;
    afterNodeAccess(old);
  }
  else
    removeNode(hash, key, null, false, true);
  return v;
}

相信只看变量名就能知道这段代码啥意思了。。如果要put的key已存在,那么就调用传进来的方法。而throwingMerger的做法就是抛了个异常。所以到这里就可以知道写的代码为什么呲了。。

如果不想抛异常的话,自己传进去一个方法即可,上述代码可以改成:

Map<Integer, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(oldValue, newValue) -> newValue));

这样就做到了使用新的value替换原有value。

写代码调方法时,多看源码实现,注意踩坑!

到此这篇关于Java8 Collectors.toMap的坑的文章就介绍到这了,更多相关Java8 Collectors.toMap内容请搜索java学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持java学习网!

相关下载

  • Java8编程入门官方教程

    大小:233 MB

相关教程

  • 一起来了解Java的策略模式

    一起来了解Java的策略模式

    给大家整理了关于Java的教程,这篇文章主要为大家详细介绍了Java的策略模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

    发布时间:2022-06-10主题:Java策略模式

    查看详情
  • Java实现base64图片编码数据转换为本地图片的方法

    给网友们整理关于java的教程,这篇文章主要介绍了Java实现base64图片编码数据转换为本地图片的方法,涉及java编码转换及图片文件生成相关操作技巧,需要的朋友可以参考下

    发布时间:2022-06-10主题:

    查看详情
  • Java统计字符串中字符出现次数的方法示例

    Java统计字符串中字符出现次数的方法示例

    给大家整理一篇关于Java的教程,这篇文章主要介绍了Java统计字符串中字符出现次数的方法,涉及Java针对字符串的遍历、查找、计算等相关操作技巧,需要的朋友可以参考下

    发布时间:2022-06-10主题:

    查看详情
  • Java实现微信公众平台朋友圈分享功能详细代码

    为网友们分享了关于java的教程,这篇文章主要介绍了Java实现微信公众平台朋友圈分享功能详细代码,小编觉得挺不错的,这里分享给大家,供需要的朋友参考。

    发布时间:2022-06-10主题:

    查看详情
  • Java中的Random()函数及两种构造方法

    给大家整理一篇关于java的教程,Java中存在着两种Random函数分别是java.lang.Math.Random和java.util.Random,文中给大家介绍了random()的两种构造方法,感兴趣的朋友跟随小编一起看看吧

    发布时间:2022-06-10主题:

    查看详情
  • Hibernate传入Java对象创建动态表并录入数据

    为网友们分享了关于java的教程,这篇文章主要介绍了Hibernate传入Java对象创建动态表并录入数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    发布时间:2022-06-10主题:Hibernate传入Java对象

    查看详情
  • Java序列化常见实现方法代码实例

    给网友朋友们带来一篇关于Java的教程,这篇文章主要介绍了Java序列化常见实现方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    发布时间:2022-06-10主题:Java序列化

    查看详情

用户留言