使用 Java8 特性

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

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

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

关于 Collectors.toMap 方法

Collectors.toMap 有三个重载方法:

image.png

image.png

image.png

1
2
3
4
5
6
7
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
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));

异常

1
java.lang.IllegalStateException: Duplicate key A

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

1
userList.stream().collect(Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1 + n2));

输出结果:

1
2
A-> 张三李四 
C-> 王五

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

1
2
3
4
5
6
7
8
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)
);

输出结果:

1
2
3
A-> 李四
B-> 张三
C-> 王五

Collectors 类的静态工厂方法

方法 返回类型 作用
toList List< T > 把流中所有项目收集到一个 List
toSet Set< T > 把流中所有项目收集到一个 Set,删除重复项
toCollection Collection< T > 把流中所有项目收集到给定的供应源创建的集合menuStream.collect(toCollection(), ArrayList::new)
counting Long 计算流中元素的个数
sumInt Integer 对流中项目的一个整数属性求和
averagingInt Double 计算流中项目 Integer 属性的平均值
summarizingInt IntSummaryStatistics 收集关于流中项目 Integer 属性的统计值,例如最大、最小、 总和与平均值
joining String 连接对流中每个项目调用 toString 方法所生成的字符串collect(joining(", "))
maxBy Optional< T > 一个包裹了流中按照给定比较器选出的最大元素的 Optional, 或如果流为空则为 Optional.empty()
minBy Optional< T > 一个包裹了流中按照给定比较器选出的最小元素的 Optional, 或如果流为空则为 Optional.empty()
reducing 归约操作产生的类型 从一个作为累加器的初始值开始,利用 BinaryOperator 与流 中的元素逐个结合,从而将流归约为单个值累加int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum));
collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果应用转换函数int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size))
groupingBy Map< K,List< T > > 根据项目的一个属性的值对流中的项目作问组,并将属性值作 为结果 Map 的键
partitioningBy Map< Boolean , List< T >> 根据对流中每个项目应用谓词的结果来对项目进行分区