Collectors 工具类提供了许多静态工具方法来为大多数常用的用户用例创建收集器,比如将元素装进一个集合中、将元素分组、根据不同标准对元素进行汇总等。本文中将覆盖大多数常见的收集器(Collector)。
1. 规约到一个单独的值
1.1 把数据装进一个list列表中
下面我们给出第一个测试用例--将给定的任务列表的所有标题收集到一个List列表中。
import static java.util.stream.Collectors.toList;
public class Example2_ReduceValue {
public List<String> allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toList());
}
}
toList收集器通过使用List的add方法将元素添加到一个结果List列表中,toList收集器使用ArrayList作为List的实现。
1.2 将数据收集到一个Set中
如果要保证所收集的title不重复并且我们对数据的排序没有要求的话,可以采用toSet收集器。
import static java.util.stream.Collectors.toSet;
public Set<String> uniqueTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toSet());
}
toSet 方法采用HashSet作为Set的实现来储存结果集。
2. 把数据收集到一个Map中
可以使用toMap收集器将一个stream转换成一个Map。toMap收集器需要两个集合函数来提取map中的key和value。下面的代码中,Task::getTitle需要一个task并产生一个仅有一个标题的key。task -> task是一个用来返回自己的lambda表达式,上例中返回一个task。
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, task -> task));
}
可以使用Function接口中的默认方法identity来让上面的代码代码变得更简洁明了、传递开发者意图时更加直接,下面是采用identity函数的代码。
import static java.util.function.Function.identity;
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity()));
}
代码创建了一个Map,当出现相同的key时就会抛出如下的异常。
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Task{title='Read Version Control with Git book', type=READING}
at java.util.stream.Collectors.lambda$throwingMerger$105(Collectors.java:133)
toMap还有一个可以指定合并函数的变体,我们可以采用它来处理重复的副本。合并函数允许开发者指定一个解决同一个key冲突的规则。在下面的代码中,我们简单地使用最后一个value,当然你也可以写更加智能的算法来处理冲突。
private static Map<String, Task> taskMap_duplicates(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2));
}
我们还可以使用toMap的第三种变体方法来使用任何其它的Map实现,这需要指定Map 和Supplier来存放结果。
public Map<String, Task> collectToMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2, LinkedHashMap::new));
}
与toMap收集器类似,toConcurrentMap收集器可以产生ConcurrntMap来替代HashMap。