Stream Collectors - toMap

public static <T,​K,​U> Collector<T,​?,​Map<K,​U>> toMap​(Function<? super T,​? extends K> keyMapper, Function<? super T,​? extends U> valueMapper)

简单理解就是把元素放到map中保存,map中的key和value都是根据元素计算而来。

先看两个官方的例子:

Map<Student, Double> studentToGPA

   = students.stream().collect(

     toMap(Function.identity(),

           student -> computeGPA(student)));

这个例子作用很明显,就是把student集合中的每个student放到map中保存,key取student这个对象本身,value通过computeGPA这个方法对student进行计算得出。

再看一个例子:

Map<String, Student> studentIdToStudent

   = students.stream().collect(

     toMap(Student::getId,

           Function.identity()));

作用和上面一样,key取值student对象中的id,value取student这个对象本身。

再看两个例子:

void test31() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail3","adr3")));

        Map<User, String> map = userList.stream().collect(Collectors.toMap(a -> a, b -> b.getAddr()));

        map.forEach((k,v) -> System.out.println(k.toString()+ ":"+ v));

    }

运行结果:

com.azhu.java8.optionalStudy.User@769c9116:a2

com.azhu.java8.optionalStudy.User@6aceb1a5:adr3

com.azhu.java8.optionalStudy.User@6956de9:adr1

 

假设有个需求,需要把User类型的集合中的所有User取其mail为key,addr为value保存在map中返回。

void test31() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail3","adr3")));

        Map<String, String> map = userList.stream().collect(Collectors.toMap(a -> a.getEmail(), b -> b.getAddr()));

        map.forEach((k,v) -> System.out.println(k+ ":"+ v));

    }

运行结果:

mail3:adr3

mail2:a2

mail1:adr1

 

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)

相比上一个函数多了一个参数,mergeFunction根据其含义就能理解这就是一个数据合并的方法。其作用就是当集合元素中根据key计算方法得出了相同的Key值就根据mergeFunction方法对这两个key值相同的元素进行处理得到一个value。

在上面那个方法中如果存在同样的key就会抛出异常。看个例子:

void test32() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail1","adr3")));

        Map<String, String> map = userList.stream().collect(Collectors.toMap(a -> a.getEmail(), b -> b.getAddr(), (c,d) -> c+" - "+d));

        map.forEach((k,v) -> System.out.println(k+ ":"+ v));

    }

以上例子中存在两个mail1,因此如果用第一个toMap方法处理就会报异常,在这里我们添加了一个出现重复key这种情况的处理方法,我们把所有重复key的value通过“-”符号连接起来形成一个key value键值对。上面代码执行结果如下:

mail2:a2

mail1:adr1 - adr3

 

这里再说一下mergeFunction函数处理流程,入参是两个,代码中定义的是c,d;执行流程是第一次遇到重复key的时候把第一个把key对应的value赋值给c,把第二个key对应的value赋值给d,然后这两个重复key保留一个,把这两个value用“-”连接起来当作其对应的value然后继续执行,当再次遇到相同key的时候再重复上面的步骤。上面例子如果还有一个user(“mail1”,”adr4”),那运行结果就是:mail1:adr1 - adr3 – adr4

 

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> mapFactory)

这个方法又多了一个参数,根据参数字面意思也能理解这个参数是用来定义最终返回的数据类型的,上面的方法默认返回的是HashMap类型,如果我们不想要这个类型就可以添加这个参数来自定义返回的数据类型。

参数定义:Supplier<M> mapFactory  这个函数参数传递数据类型是M,再看看返回数据类型的定义:M extends Map<K,​U> 因此自定义的数据类型只能是实现Map接口的数据类型。

看个例子:

void test33() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail1","adr3")),(new User("mail1","adr4")));

        Map<String, String> map = userList.stream().collect(Collectors.toMap(a -> a.getEmail(), b -> b.getAddr(), (c,d) -> c+" - "+d));

        map.forEach((k,v) -> System.out.println(k+ ":"+ v));

        System.out.println(map.getClass().getTypeName());

       

        Map<String, String> map2 = userList.stream().collect(Collectors.toMap(a -> a.getEmail(), b -> b.getAddr(), (c,d) -> (c+" - "+d), TreeMap::new));

        map2.forEach((k,v) -> System.out.println(k+ ":"+ v));

        System.out.println(map2.getClass().getTypeName());

    }

执行结果:

mail2:a2

mail1:adr1 - adr3 - adr4

java.util.HashMap

mail1:adr1 - adr3 - adr4

mail2:a2

java.util.TreeMap

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java stream Collectors.toMap是一个流式处理方法,用于将一个List集合转换为Map集合。它接受三个参数:第一个参数指定了作为Map的key值的属性或方法引用,第二个参数指定了作为Map的value值的属性或方法引用,第三个参数用于处理key重复的情况。 通过使用Collectors.toMap方法,可以将一个List集合中的元素按照指定的属性或方法引用作为key值,将整个对象或属性值作为value值,构建出一个key值唯一的Map集合。 举例来说,如果有一个List<proVo>对象的集合,我们希望将其中的proVo对象按照id作为key,name作为value,构建成一个Map集合,可以使用如下代码: Map<Long, String> map = list.stream().collect(Collectors.toMap(proVo::getId, proVo::getName)); 这样就可以得到一个key为id,value为name的Map集合。 另外,如果在转换过程中遇到了key重复的情况,可以通过第三个参数来处理。比如可以选择保留前一个元素的值,或者保留后一个元素的值,或者进行其他自定义的处理。 例如: Map<Long, String> map = list.stream().collect(Collectors.toMap(proVo::getId, proVo::getName, (k1, k2) -> k1)); 这样当遇到key重复的情况时,会保留前一个元素的值作为value。 总之,java stream Collectors.toMap方法是用于将List集合转换为Map集合的一个便捷方法,可以根据需求选择合适的参数来进行处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [java8stream源码-streams:用于针对旧设备的Android项目的java.util.stream库的非常不完整的重新实现](https://download.csdn.net/download/weixin_38690522/19389466)[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: 50%"] - *2* *3* [【业务功能篇35】Java Stream流 :Collectors.toMap](https://blog.csdn.net/studyday1/article/details/131454535)[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: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值