【前言】
在很多编码时候,我们需要将我们的 List 对象集合,转成为简单的 Map 集合,从而方便很多后续操作。
比如:我们现在有一个用户类 User 如下:
-
public
class User {
-
-
// 用户ID
-
private
long id;
-
-
// 用户名称
-
private String name;
-
-
// 相关constrator,getter,setter,toString()方法已省略
-
}
那么,我们可以简单的初始化得到一个 List<User> 的数组,如下所示:
-
List<User> users = Arrays.asList(
-
new User(
101,
"Jack"),
-
new User(
102,
"Kreas"),
-
new User(
103,
"Marry"),
-
new User(
104,
"Timi"),
-
new User(
105,
"Alice"));
如果我们现在需要在该 List 集合中找出 id = 102,id =104 这两个用户的话。
我们也许会如下这么做:
运行程序得到结果为:
当然,这么做是可以的,但这样代码可能会略显臃肿,
既然我们以 id 的方式去查找,何不妨把 List 转成 以 id 为键,对象为值的方式存于Map中。
这样操作起来就会显得更加的巧便:
【2】引入 Collectors.toMap()
在上面的示例代码中,我们将list通过遍历,将它转化为了一个map。
然而在 Java8 中,list 转 map 可以不用如此,我们可以利用 Java 8 stream 特性对集合进行操作,最后采用 Collectors.toMap() 将List 转为 Map。
比如上面的写法可以等价于:
他的结果和上面也是一致的:
这样,我们的代码看起来就精简了许多,从最初的13行代码变化到6行代码,再到最后的3行代码。
【3】拓展
下面我们再了解下常用的 List 转 Map 的常见方式和一些注意事项:
【3.1】常见方式:
(3.1.1)List 转 Map,值为对象:
Map<Long, User> map = users.stream().collect(Collectors.toMap(User::getId, o -> o));
(3.1.2)List 转 Map,值为属性:
Map<Long, String> map = users.stream().collect(Collectors.toMap(User::getId, User::getName));
(3.1.3) List 转 Map,值为属性,且二次加工:
示例:姓名值后面统一加上一个 "_OK"字符
Map<Long, String> map = users.stream().collect(Collectors.toMap(User::getId, o -> o.getName() + "_OK"));
【3.2】注意事项:
(3.2.1)map 中的 key 值不能重复
首先我们先看下,正常数据的一段代码:
下面我们将103的Marry的ID改为104,这样我们的数据就存在了两个ID为104的记录,然后我们再运行一次程序,可以发现已经出现了异常:
其实,这个报错我们也能理解,毕竟所有Map的键是也不能重复的。
那么,我们通常会有哪些解决办法呢?
首先,我们可以以第一个键为准,后面的则自动忽略,
我们只需要在 Collectors.toMap() 方法里增加一个 Lamda表达式,具体写法如下:
可以看到,程序不再报异常,且第二个id为104的 Timi 已经被忽略了。
或者,我们采用覆盖原则,如果发现一个有重复的键,则自动覆盖之前值,具体方法如下:
可以发现,他与上个方式,唯一的区别就是选择的取值不同,没错,如果要想保留前面的数据就取参数1,要想保留后面的数据就取参数2。
你也许内心在想:如果我都想保留,可不可以呢?
当然可以!但这里Map值的类型是String类型,我们可以将所有ID相同的值连接,然后存放于Map中,写法如下:
可以看到,id = 104 的三个人都存于map中了。
(3.2.2)值不能为空
我们将id恢复正常,然后将最后一个的名称置空为null,运行程序:
可以发现,此时又出现了异常。
解决办法:我们可以将null值默认为空字符串,具体如下:
转载:https://blog.csdn.net/sunnyzyq/article/details/108646765