JDK1.8为集合提供了Stream流,可以快速的将List集合转换为Map集合。
1. 数据准备:
public class Test {
//数据准备
@Data
public static class User {
private Integer id;
private Integer schoolId;
private String userName;
private String edu;
}
static private List users = new ArrayList<>();
static {
User u1 = new User();
u1.setId(1001);
u1.setSchoolId(100);
u1.setUserName("小1");
u1.setEdu("001");
User u2 = new User();
u2.setId(1002);
u2.setSchoolId(100);
u2.setUserName("小2");
u2.setEdu("002");
User u3 = new User();
u3.setId(2010);
u3.setSchoolId(200);
u3.setUserName("小3");
u3.setEdu("001");
User u4 = new User();
u4.setId(3001);
u4.setSchoolId(300);
u4.setEdu("003");
users.add(u1);
users.add(u2);
users.add(u3);
users.add(u4);
}
}
2. 使用方法:
- 若是以User对象的id属性作为key,User对象为value。转换成的一个Map。
public static void main(String[] args) {
//将List转换为Map
Map userMap = users.stream().collect(Collectors.toMap(User::getId,
Function.identity()));
System.out.println(JSON.toJSONString(userMap));
}
效果一览:
null:{"edu":"004","schoolId":400,"userName":"小5"},
3001:{"edu":"003","id":3001,"schoolId":300,"userName":"小4"},
1001:{"edu":"001","id":1001,"schoolId":100,"userName":"小1"},
2010:{"edu":"001","id":2010,"schoolId":200,"userName":"小3"},
1002:{"edu":"002","id":1002,"schoolId":100,"userName":"小2"}
}
- 若是将对象的某个属性作为key,某个属性作为value。转换成一个Map。
public static void main(String[] args) {
//将List转换为Map
Map stringMap = users.stream().
collect(Collectors.toMap(User::getId,
User::getEdu));
System.out.println(JSON.toJSONString(stringMap));
}
3. 存在的问题
- key相同的情况
public static void main(String[] args) {
//将List转换为Map
Map userMap = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getEdu,
Function.identity()));
System.out.println(JSON.toJSONString(userMap));
}
出现异常:重复秘钥
Exception in thread "main" java.lang.IllegalStateException: Duplicate key
- value为null的情况
public static void main(String[] args) {
//将List转换为Map
Map stringMap = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getId, User::getUserName));
System.out.println(JSON.toJSONString(stringMap));
}
出现异常:空指针异常
Exception in thread "main" java.lang.NullPointerException
4. 解决方案
JDK8的Collectors.toMap()提供了第三个参数,来处理上面的问题。
- 当出现重复的key问题时:合并value值。
public static void main(String[] args) {
//将List转换为Map,解决key冲突的问题。
Map userMap = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getEdu,
//value的值
Function.identity(),
//合并两个value值:k1是旧值,k2是新值。
(k1, k2) -> {
log.info(JSON.toJSONString(k1));
log.info(JSON.toJSONString(k2));
return k2;
}));
System.out.println(userMap);
}
- 当出现value为null的情况:
public static void main(String[] args) {
//将List转换为Map,解决key冲突的问题。
Map> collect = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getEdu,
//value的值,是集合的结构
p -> {
//获取value值
List users = new ArrayList<>();
users.add(p.getUserName());
return users;
},
//集合合并
(List k1, List k2) -> {
k1.addAll(k2);
return k1;
}));
System.out.println(collect);
}
得到的集合:
{001=[小1, 小3, null], 002=[小2]}
5. 扩展
- 转换为TreeMap:
public static void main(String[] args) {
//将List转换为Map,解决key冲突的问题。
TreeMap collect = users.stream().
//User对象的edu属性作为key,但是会存在key相同的情况
collect(Collectors.toMap(User::getEdu,
//value的值,是集合的结构
User::getId,
(k1, k2) -> k1, TreeMap::new
));
System.out.println(collect);
}
- 对List进行分组:
public static void main(String[] args) {
Map> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu));
System.out.println(collect);
}
若是想得到的value是某个值,可以使用mapping来进行映射:
public static void main(String[] args) {
Map> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu,
Collectors.mapping(User::getUserName, Collectors.toList())));
System.out.println(collect);
}
若是Map中key对应的是一个List集合,那么可以使用group by
来实现
推荐阅读:JDK8对List进行分组操作(stream的groupby)
推荐阅读
List转换为TreeMap
List转换为HashMap的注意事项
Java8函数式编程(三):Collectors.groupingBy