写代码的时候,经常会需要处理拿到的数据,比如把list转成map,就有好多种写法,所以写文章理一下区别。
假设我们有一个实体类User
@Data
public class User{
private Long id;
private String name;
private Integer age;
}
然后先列一下不涉及对象的list转map
1.将List转为Map,key是列表元素,value是索引:
List<String> list = Arrays.asList("a", "b", "c");
Map<String, Integer> map = list.stream().collect(Collectors.toMap(e -> e, list::indexOf));
2.将List转为Map,同时转换元素类型:
List<User> list = getUserList();
Map<Integer, String> map = list.stream().collect(Collectors.toMap(User::getId, User::getName));
3.将List转为Map,对象的map,同时还可以过滤或者去重
Map<Integer, User> map = list.stream()
.filter(u -> u.getAge() > 20)
.collect(Collectors.toMap(User::getId, u -> u));
4.归组为Map:
Map<String, List<User>> map = list.stream().collect(Collectors.groupingBy(User::getCity));
都很好用,其中我想讨论的是第三种情况,也就是将List转为Map
我感兴趣的主要是Collectors.toMap()这个toMap里的几种写法
java.util.stream.Collectors类的toMap()方法,是一个非常有用的工具方法,可以将Stream中的元素收集到一个Map中。
最基础的版本,通过两个映射函数分别提取key和value,将元素收集到Map中。例如:
List<User> list = ...;
Map<Integer, String> map = list.stream().collect(Collectors.toMap(User::getId, User::getName));
这个版本增加了一个mergeFunction参数,用于处理key冲突的情况,当出现重复的key时,会使用这个函数进行处理。
map = list.stream().collect(Collectors.toMap(User::getId, User::getName, (oldValue, newValue) -> newValue));
这里在key冲突时保留新值。
这个版本额外增加了一个mapSupplier参数,用于指定返回的Map类型,例如:
map = list.stream().collect(Collectors.toMap(User::getId, User::getName, (oldValue, newValue) -> newValue, HashMap::new));
这里指定了使用HashMap。
如果知道key不会冲突,可以只用keyMapper, valueMapper和mapSupplier这三个参数。