gpt4 book ai didi

Java8中List转Map(Collectors.toMap) 的技巧分享

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java8中List转Map(Collectors.toMap) 的技巧分享由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

前言

在实际项目中我们经常会用到 List 转 Map 操作,在过去我们可能使用的是 for 循环遍历的方式。举个例子:

先定义类:

?
1
2
3
4
5
6
7
// 简单对象
@Accessors (chain = true ) // 链式方法
@lombok .Data
class User {
     private String id;
     private String name;
}

然后有这样一个 List:

?
1
2
3
4
5
List<User> userList = Lists.newArrayList(
         new User().setId( "A" ).setName( "张三" ),
         new User().setId( "B" ).setName( "李四" ),
         new User().setId( "C" ).setName( "王五" )
);

我们希望转成 Map 的格式为:

A-> 张三 B-> 李四 C-> 王五 。

过去的做法(循环):

?
1
2
3
4
Map<String, String> map = new HashMap<>();
for (User user : userList) {
     map.put(user.getId(), user.getName());
}

使用 Java8 特性

Java8 中新增了 Stream 特性,使得我们在处理集合操作时更方便了.

以上述例子为例,我们可以一句话搞定:

?
1
userList.stream().collect(Collectors.toMap(User::getId, User::getName));

当然,如果希望得到 Map 的 value 为对象本身时,可以这样写:

?
1
userList.stream().collect(Collectors.toMap(User::getId, t -> t));

 或:

?
1
userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

关于 Collectors.toMap 方法

Collectors.toMap 有三个重载方法:

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

参数含义分别是:

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

还是用上面的例子,如果 List 中 userId 有相同的,使用上面的写法会抛异常:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
List<User> userList = Lists.newArrayList(
         new User().setId( "A" ).setName( "张三" ),
         new User().setId( "A" ).setName( "李四" ), // Key 相同
         new User().setId( "C" ).setName( "王五" )
);
userList.stream().collect(Collectors.toMap(User::getId, User::getName));
 
// 异常:
java.lang.IllegalStateException: Duplicate key 张三
     at java.util.stream.Collectors.lambda$throwingMerger$ 114 (Collectors.java: 133 )
     at java.util.HashMap.merge(HashMap.java: 1245 )
     at java.util.stream.Collectors.lambda$toMap$ 172 (Collectors.java: 1320 )
     at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java: 169 )
     at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java: 1374 )
     at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java: 481 )
     at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java: 471 )
     at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java: 708 )
     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java: 234 )
     at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java: 499 )
     at Test.toMap(Test.java: 17 )
     ...

这时就需要调用第二个重载方法,传入合并函数,如:

?
1
2
3
4
5
userList.stream().collect(Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1 + n2));
 
// 输出结果:
A-> 张三李四
C-> 王五

第四个参数(mapSupplier)用于自定义返回 Map 类型,比如我们希望返回的 Map 是根据 Key 排序的,可以使用如下写法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
List<User> userList = Lists.newArrayList(
         new User().setId( "B" ).setName( "张三" ),
         new User().setId( "A" ).setName( "李四" ),
         new User().setId( "C" ).setName( "王五" )
);
userList.stream().collect(
     Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1, TreeMap:: new )
);
 
// 输出结果:
A-> 李四
B-> 张三
C-> 王五

总结

到此这篇关于Java8中List转Map(Collectors.toMap) 的文章就介绍到这了,更多相关Java8 List转Map(Collectors.toMap)内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。

原文链接:https://zhangzw.com/posts/20191205.html 。

最后此篇关于Java8中List转Map(Collectors.toMap) 的技巧分享的文章就讲到这里了,如果你想了解更多关于Java8中List转Map(Collectors.toMap) 的技巧分享的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com