Java 8 Collectors (collector) API is simple to use

Introduction to Collectors API

The java.util.stream.Collectors class provides us with rich convection operations. Next, let's take a look at the specific functions of these APIs

  • 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));
        }

Grouping collector functions into the Collector abstraction is syntactically simpler, but the real benefit comes when you start grouping collectors together, such as when you want to create complex aggregated results. Next, let's try to combine various collectors to see.

  • Let's look at an example that combines various collectors
        /**
         * 
         * @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);
            }
        }
  • Count the tallest students in each province in a class
        /**
         * 返回每个省份的最高学生的所有信息。
         * @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)))));
        }
  • Returns the average height of students, grouped first by gender and then by province.
        /**
         * 先以性别分组然后再以省份分组,返回学生的平均身高。
         * @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))));
        }
concluding remarks

All code used in the use case can be downloaded on GitHub .

Reference documentation

java.util.stream official documentation

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325657143&siteId=291194637