Collectors API介绍
java.util.stream.Collectors类为我们提供了丰富的对流的操作,接下来我们来看看这些API的具体功能
- averagingDouble(ToDoubleFunction<? super T> mapper)
/*
* averagingDouble/Int/Long
* 汇总求出平均值
*/
public double averagingDoubleTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(averagingDouble(student -> student.getHeight()));
}
- collectingAndThen(Collector
/*
* collectingAndThen 将收集来的结果进行而外的转换
* 本例中将收集的结果放入不可变List中。
*/
public List<String> collectingAndThenTest(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.map(student -> student.getName())
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
}
- counting()
/*
* 简单的计数器,简单的计算流元素。
*/
public long countingTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(counting());
}
- groupingBy(Function<? super T,? extends K> classifier)
/*
* 通过省份将学生分组到List中。
*/
public Map<String, List<Student>> groupingByToList(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingBy(Student::getFrom));
}
- groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)
/*
* 通过省份将学生分组到Set中。
*/
public Map<String, Set<Student>> groupingByToSet(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingBy(Student::getFrom, toSet()));
}
- groupingBy(Function<? super T,? extends K> classifier, Supplier
/*
* 通过省份将学生分组到Set中。并返回一个TreeMap.
*/
public Map<String, Set<Student>> groupingByToTreeMap(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingBy(Student::getFrom, TreeMap::new, toSet()));
}
- groupingByConcurrent(Function<? super T,? extends K> classifier)
/*
* 返回并发的Map
*/
public Map<String, List<Student>> groupingByConcurrentTest(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingByConcurrent(Student::getFrom));
}
- groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)
/*
* 返回并发的Map
*/
public Map<String, Set<Student>> groupingByConcurrentToSet(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingByConcurrent(Student::getFrom, toSet()));
}
- groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier
/*
* 返回并发的Map
*/
public Map<String, Set<Student>> groupingByConcurrentToSkipMap(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingByConcurrent(Student::getFrom, ConcurrentSkipListMap::new, toSet()));
}
- joining()
/*
* 返回所有的学生的姓名
*/
public String joiningTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.map(Student::getName)
.collect(joining());
}
- joining(CharSequence delimiter)
/*
* 返回所有的学生的姓名,姓名之间用逗号分割。
*/
public String joiningDelimiter(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.map(Student::getName)
.collect(joining(", "));
}
- joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
/*
* 返回所有的学生的姓名,姓名之间用逗号分割,并放在中括号里边。
*/
public String joiningDelimiterPreAndSuf(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.map(Student::getName)
.collect(joining(", ", "[", "]"));
}
- mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)
/*
* 以省份分组,并返回学生姓名的集合。
*/
public Map<String, List<String>> mappingTest(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingBy(Student::getFrom, mapping(Student::getName, toList())));
}
- maxBy(Comparator<? super T> comparator)
/**
*
* @param students
* @return
* 返回身高最高的学生
*/
public Student maxByTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(maxBy(Comparator.comparingDouble(Student::getHeight)))
.get();
}
- minBy(Comparator<? super T> comparator)
/**
*
* @param students
* @return 返回体重最轻的学生。
*/
public Student minByTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(minBy(Comparator.comparingDouble(Student::getWeight)))
.get();
}
- partitioningBy(Predicate<? super T> predicate)
/**
*
* @param students
* @return
* 根据Predicate将流分割,并将它们组织成一个 Map<Boolean, List<T>>返回。
*/
public Map<Boolean, List<Student>> partitioningByTest(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(partitioningBy(student -> Constants.Province.SHANNXI.equals(student.getFrom())));
}
- partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream)
/**
*
* @param students
* @return
* 根据Predicate将流分割,并将它们组织成一个 Map<Boolean, List<T>>返回。
*/
public Map<Boolean, Set<Student>> partitioningByToSet(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(partitioningBy(student -> Constants.Province.SHANNXI.equals(student.getFrom()), toSet()));
}
- reducing(BinaryOperator
/**
*
* @param students
* @return
* 返回一个班级中每个省份的身高最高的学生。
*/
public Map<String, Optional<Student>> reducingTest(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
Comparator<Student> byHeight = Comparator.comparing(Student::getHeight);
return students.stream()
.collect(groupingBy(Student::getFrom, reducing(BinaryOperator.maxBy(byHeight))));
}
- summarizingDouble(ToDoubleFunction<? super T> mapper)
/**
* summarizingDouble/Int/Long
* @param students
* @return DoubleSummaryStatistics
* 用另一种方式来求学生的平均体重。
*/
public Double summarizingDoubleTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(summarizingDouble(Student::getWeight))
.getAverage();
}
- summingDouble(ToDoubleFunction<? super T> mapper)
/**
* 求和,如果元素不存在,则结果为0.
* @param students
* @return
* 求学生的平均身高
*/
public double summingDoubleTest(List<Student> students) {
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(summingDouble(Student::getHeight)) / students.size();
}
- toCollection(Supplier
/**
*
* @param students
* @return
* 将元素放入制定的集合中
*/
public List<String> toCollectionToList(List<Student> students){
return students.stream()
.map(Student::getName)
.collect(toCollection(ArrayList::new));
}
- toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
/**
*
* @param students
* @return
* 获取学生的成绩
*/
public Map<String, Map<String, Double>> toConcurrentMapTest(List<Student> students){
return students.stream()
.collect(toConcurrentMap(Student::getName, Student::getScores));
}
- toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
/**
*
* @param students
* @return
*/
public Map<String, Date> toMapTest(List<Student> students){
return students.stream()
.collect(toMap(Student::getName, Student::getBirthday));
}
将收集器函数分组到 Collector 抽象中在语法上更简单,但实际收益来自您开始将收集器组合在一起时,比如您想要创建复杂的汇总结果。接下来我们来尝试将各种收集器组合起来看看。
- 让我们看一个将各种收集器综合起来的例子
/**
*
* @param address
* @return
* @throws FileNotFoundException
* 统计一篇文章的词频直方图。
*/
public Map<String, Long> toMapForWord(String address) throws FileNotFoundException{
Objects.requireNonNull(address, "The parameter cannot be empty");
BufferedReader reader = null;
Pattern whitespace = Pattern.compile("\\s+");
try {
reader = new BufferedReader(new FileReader(new File(address)));
return reader.lines()
.flatMap(string -> whitespace.splitAsStream(string))
.collect(groupingBy(String::toLowerCase, counting()));
} catch (Exception e) {
// Error log
return new HashMap<String, Long>();
} finally {
StreamUtils.close(reader);
}
}
- 统计一个班级中每个省份身高最高的学生
/**
* 返回每个省份的最高学生的所有信息。
* @param students
* @return
*/
public Map<String, Map<String, Optional<Student>>> accountMaxHeightByProvince(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(groupingBy(Student::getFrom,
groupingBy(Student::getName,
maxBy(Comparator.comparingDouble(Student::getHeight)))));
}
- 先以性别分组然后再以省份分组,返回学生的平均身高。
/**
* 先以性别分组然后再以省份分组,返回学生的平均身高。
* @param students
* @return
*/
public Map<Boolean, Map<String, Double>> averageHeightByProvince(List<Student> students){
Objects.requireNonNull(students, "The parameter cannot be empty");
return students.stream()
.collect(partitioningBy(student -> "M".equals(student.getGender()),
groupingBy(Student::getFrom, averagingDouble(Student::getHeight))));
}
结束语
用例中所有使用到的代码可以在GitHub上下载。
参考文档