JDK1.8為集合提供了Stream流,可以快速的將List集合轉(zhuǎn)換為Map集合。
1. 數(shù)據(jù)準(zhǔn)備:
public class Test {
//數(shù)據(jù)準(zhǔn)備
@Data
public static class User {
private Integer id;
private Integer schoolId;
private String userName;
private String edu;
}
static private List<User> 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。轉(zhuǎn)換成的一個Map。
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map
Map<Integer, User> 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。轉(zhuǎn)換成一個Map。
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map
Map<Integer, String> 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轉(zhuǎn)換為Map
Map<String, User> userMap = users.stream().
//User對象的edu屬性作為key,但是會存在key相同的情況
collect(Collectors.toMap(User::getEdu,
Function.identity()));
System.out.println(JSON.toJSONString(userMap));
}
出現(xiàn)異常:重復(fù)秘鑰
Exception in thread "main" java.lang.IllegalStateException: Duplicate key
- value為null的情況
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map
Map<Integer, String> stringMap = users.stream().
//User對象的edu屬性作為key,但是會存在key相同的情況
collect(Collectors.toMap(User::getId, User::getUserName));
System.out.println(JSON.toJSONString(stringMap));
}
出現(xiàn)異常:空指針異常
Exception in thread "main" java.lang.NullPointerException
4. 解決方案
JDK8的Collectors.toMap()提供了第三個參數(shù),來處理上面的問題。
- 當(dāng)出現(xiàn)重復(fù)的key問題時:合并value值。
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map,解決key沖突的問題。
Map<String, User> 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);
}
- 當(dāng)出現(xiàn)value為null的情況:
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map,解決key沖突的問題。
Map<String, List<String>> collect = users.stream().
//User對象的edu屬性作為key,但是會存在key相同的情況
collect(Collectors.toMap(User::getEdu,
//value的值,是集合的結(jié)構(gòu)
p -> {
//獲取value值
List<String> users = new ArrayList<>();
users.add(p.getUserName());
return users;
},
//集合合并
(List<String> k1, List<String> k2) -> {
k1.addAll(k2);
return k1;
}));
System.out.println(collect);
}
得到的集合:
{001=[小1, 小3, null], 002=[小2]}
5. 擴(kuò)展
- 轉(zhuǎn)換為TreeMap:
public static void main(String[] args) {
//將List轉(zhuǎn)換為Map,解決key沖突的問題。
TreeMap<String, Integer> collect = users.stream().
//User對象的edu屬性作為key,但是會存在key相同的情況
collect(Collectors.toMap(User::getEdu,
//value的值,是集合的結(jié)構(gòu)
User::getId,
(k1, k2) -> k1, TreeMap::new
));
System.out.println(collect);
}
- 對List進(jìn)行分組:
public static void main(String[] args) {
Map<String, List<User>> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu));
System.out.println(collect);
}
若是想得到的value是某個值,可以使用mapping來進(jìn)行映射:
public static void main(String[] args) {
Map<String, List<String>> collect = users.stream().
collect(Collectors.groupingBy(User::getEdu,
Collectors.mapping(User::getUserName, Collectors.toList())));
System.out.println(collect);
}
若是Map中key對應(yīng)的是一個List集合,那么可以使用group by來實現(xiàn)
推薦閱讀:JDK8對List進(jìn)行分組操作(stream的groupby)