Collectors.toMap使用详解

这篇具有很好参考价值的文章主要介绍了Collectors.toMap使用详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、使用规则

在实际项目中我们经常会有 List 转 Map 操作,在过去(JAVA8以前)我们可能使用的是 for 循环遍历的方式,这种方式就不做过多赘述。这里主要讲解使用 Collectors.toMap 方式及使用过程需注意的地方,避免踩坑

二、源码及方法

三个重载的方法如下:

//方法一:2个参数
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);
}
//方法二:3个参数
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);
}
//方法三:4个参数
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);
}

参数含义分别是:

  • keyMapper:Key 的映射函数。
  • valueMapper:Value 的映射函数。
  • mergeFunction:当 Key 冲突时,调用的合并方法。
  • mapSupplier:Map 构造器,在需要返回特定的 Map 时使用。

三、代码示例

首先我们建一个Dept类,属性分别有id,name,group,然后构造一个list:

public class ListToMapDemo {
    public static void main(String[] args) {
        List<Dept> list = new ArrayList<>();
        list.add(new Dept(1,"部门一","1"));
        list.add(new Dept(2,"部门二","2"));
        list.add(new Dept(3,"部门三","3"));
        list.add(new Dept(4,"部门四","4"));
        
    }

    static class Dept{
        private Integer id;
        private String name;
        private String group;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getGroup() {
            return group;
        }

        public void setGroup(String group) {
            this.group = group;
        }

        public Dept(Integer id, String name, String group) {
            this.id = id;
            this.name = name;
            this.group = group;
        }
 @Override
        public String toString() {
            return "Dept{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", group='" + group + '\'' +
                    '}';
        }
    }
}

1.将list转成以id为key的map,value是id对应的Dept对象

Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId, Function.identity()));
System.out.println(map);
  
 运行结果如下:
 {1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'}, 
 3=Dept{id=3, name='部门三', group='3'}, 4=Dept{id=4, name='部门四', group='4'}}      

2.假如id存在重复值,则会报错Duplicate key xxx, 解决方案是

只取后一个key及value:

List<Dept> list = new ArrayList<>();
list.add(new Dept(1,"部门一","1"));
list.add(new Dept(2,"部门二","2"));
list.add(new Dept(3,"部门三","3"));
list.add(new Dept(3,"部门四","4"));
Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId, Function.identity(),(oldValue, newValue) -> newValue));
System.out.println(map);

运行结果如下:
{1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'}, 3=Dept{id=3, name='部门四', group='4'}}

只取前一个key及value:

 Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId,Function.identity(),(oldValue,newValue) -> oldValue));
System.out.println(map);

运行结果如下:
{1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'},
 3=Dept{id=3, name='部门三', group='3'}}

3.想获得一个id和name对应的Map<Integer, String>

  Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId,Dept::getName));
  System.out.println(map);
运行结果如下:

{1=部门一, 2=部门二, 3=部门三, 4=部门四}

注意:name可以为空字符串但不能为null,否则会报空指针,解决方案:

Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId, e -> e.getName() == null ? "" : e.getName()));

假如存在id重复,两个vaue可以这样映射到同一个id:

    Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId,Dept::getName,(e1, e2)->e1+","+e2));
System.out.println(map);

运行结果如下:
{1=部门一, 2=部门二, 3=部门三,部门四}

4.把Dept集合按照group分组到map中

  Map<String, List<Dept>> map = list.stream().collect(Collectors.groupingBy(Dept::getGroup));
System.out.println(map);


运行结果如下:
{1=[Dept{id=1, name='部门一', group='1'}], 2=[Dept{id=2, name='部门二', group='2'}], 
3=[Dept{id=3, name='部门三', group='3'}, Dept{id=3, name='部门四', group='3'}]}

5.过滤去重,两个List

Map<String, Dept> map2 = list2.stream().collect(Collectors.toMap(Dept::getId,Function.identity()));

//把List1和List2中id重复的Dept对象的name取出来:

List strings = list1.stream().map(Dept::getId).filter(map2::containsKey).map(map2::get).map(Dept::getName).collect(Collectors.toList());

System.out.println(strings);// 输出 [部门2, 部门3]

四、总结

Collectors.toMap 确实带来方便,但是,与此同时,也需要注意两点(你也可以认为是2个坑):

需考虑是否有key重复情况;
需考虑是否有value为null情况。
以上两点在阿里的Java开发手册中也明确指出:
Collectors.toMap使用详解文章来源地址https://www.toymoban.com/news/detail-512371.html

到了这里,关于Collectors.toMap使用详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详细解决java中的Collectors.toMap引起的java.lang.IllegalStateException: Duplicate key xxx 的错误

    今天,测试在禅道上给我指出一个正式环境 bug ,如下图所示: 即 java.lang.IllegalStateException: Duplicate key 2 。 根据 java.lang.IllegalStateException: Duplicate key 2 可知,这是 java 抛出的存在 2个重复键 的错误。 如果想要弄清楚错误原因,通过如下几个步骤分析: 首先,看到这个错误信息

    2024年01月19日
    浏览(60)
  • Java8 Collectors类详解(一)

      Collectors 类是用于对流进行收集和汇总的工具类。它提供了许多方法来对流进行分组、统计、转换、分区、连接、归约等操作,使得处理集合类数据变得更加方便。         在使用 Collectors 类时,我们可以通过调用其中的方法来实现对流的不同处理方式。例如,将流中

    2024年02月07日
    浏览(53)
  • 实际上手体验maven面对冲突Jar包的加载规则 | 京东云技术团队

    相信大家在日常的开发过程中都遇到过Jar包冲突的问题,emm,在最近处理业务需求时我也遇到了不同版本jar包冲突导致项目加载出错的问题。主要是一个完整的项目会不可避免的使用第三方的Jar包来实现功能开发,各种第三方包之间可能会存在依赖关系,不同版本的依赖就会

    2024年02月16日
    浏览(36)
  • Java stream流toMap使用过程中空指针问题

    Java8中stream操作list时常见的一个错误: 排查原因: 定位到代码中发现从数据查询是存在数据的 排查stream前对象为null的情况,那问题只能出现在toMap这里了 我们需要知道toMap是怎么帮我们封装数据的,先搞明白toMap的原理,点击源码可以看到他并不是通过map中的put方法封装数

    2024年02月05日
    浏览(38)
  • 【微服务】java 规则引擎使用详解

    目录 一、什么是规则引擎 1.1 规则引擎概述 1.2 规则引擎执行过程

    2024年02月05日
    浏览(48)
  • 【Vue】Vue中mixins的使用方法及实际项目应用详解

    (1)mixin基础 官网解释(Vue2.x): 混入(mixin)提供了一种非常灵活的方式,来分发Vue组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。 如何理解mixins?我们可以将mixins理解成一

    2023年04月09日
    浏览(58)
  • Collectors.partitioningBy使用将List分解成两个集合

    结果:

    2024年02月13日
    浏览(51)
  • nginx使用详解:转发规则、负载均衡、server_name

    该指令用于匹配 URL,语法如下: 指令 说明 = 用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配 成功,就停止继续向下搜索并立即处理该请求。 ~ 用于表示 uri 包含正则表达式,并且区分大小写。 ~* 用于表示 uri 包含正则表达式,并且不区分大小写。

    2024年01月17日
    浏览(50)
  • 使用Java8 Stream流中的Collectors.collectingAndThen()方法去重

    Collectors.collectingAndThen() 根据对象属性进行去重操作 Collectors.collectingAndThen()方法属于java8 Stream流中的 java.util.stream.Collectors ,此类实现了 java.util.stream.Collector 接口,还提供了大量的方法对Stream流中的元素进行 map 和 reduce 操作 在获取任务的时候,会出现id重复的状况,利用 Co

    2024年02月09日
    浏览(63)
  • ⑩② 【MySQL索引】详解MySQL`索引`:结构、分类、性能分析、设计及使用规则。

    个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 索引 : 什么是索引(index) ? 索引(index)是帮助MySQL 高效获取数据的数据结构 (有序):在数据之外,数据库系统

    2024年02月05日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包