Collectors方法大全

  • 一、所用示例类
  • 1. Student
  • 2. GradeType
  • 3. CollectorsTest
  • 二、Collectors方法及使用
  • 1. Collectors.toCollection()
  • 2. Collectors.toList() / Collectors.toSet()
  • 3. Collectors.toMap(Function, Function) / Collectors.toConcurrentMap(Function, Function)
  • 4. Collectors.toMap(Function, Function, BinaryOperator) / Collectors.toConcurrentMap(Function, Function, BinaryOperator)
  • 5. Collectors.collectingAndThen(Collector, Function)
  • 6. Collectors.joining() / joining(delimiter) / joining(delimiter, prefix, suffix)
  • 7. Collectors.mapping(Function, Collector)
  • 8. Collectors.maxBy(Comparator) / Collectors.minBy(Comparator)
  • 9. Collectors.counting()
  • 10. Collectors.groupingBy(Function) / groupingByConcurrent(Function)
  • 11. Collectors.groupingBy(Function, Collector) / groupingByConcurrent(Function, Collector)
  • 12. Collectors.groupingBy(Function, Supplier, Collector) / groupingByConcurrent(Function, Supplier, Collector)
  • 13. Collectors.summingDouble(ToDoubleFunction) / Collectors.summingInt(ToIntFunction) / Collectors.summingLong(ToLongFunction)
  • 14. Collectors.averagingDouble(ToDoubleFunction) / Collectors.averagingInt(ToIntFunction) / Collectors.averagingLong(ToLongFunction)
  • 15. Collectors.partitioningBy(Predicate)
  • 16. Collectors.partitioningBy(Predicate, Collector)
  • 三、完整代码
  • 参照链接


一、所用示例类

1. Student

public class Student {
    // ID
    private String id;
    // 姓名
    private String name;
    // 总分
    private int totalScore;
    // 是否本地人
    private boolean local;
    // 年级
    private GradeType gradeType;

    public Student(String id, String name, int totalScore, boolean local, GradeType gradeType) {
        this.id = id;
        this.name = name;
        this.totalScore = totalScore;
        this.local = local;
        this.gradeType = gradeType;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getTotalScore() {
        return totalScore;
    }

    public void setTotalScore(int totalScore) {
        this.totalScore = totalScore;
    }

    public boolean isLocal() {
        return local;
    }

    public void setLocal(boolean local) {
        this.local = local;
    }

    public GradeType getGradeType() {
        return gradeType;
    }

    public void setGradeType(GradeType gradeType) {
        this.gradeType = gradeType;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", totalScore=" + totalScore +
                ", local=" + local +
                ", gradeType=" + gradeType +
                '}';
    }
}

2. GradeType

/**
 * 年级类型 枚举
 */
public enum GradeType {
    ONE_GRADE, // 一年级
    TWO_GRADE,  // 二年级
    THREE_GRADE; // 三年级
}

3. CollectorsTest

public class CollectorsTest {
    private static final List<Student> students = new ArrayList<>(16);

    static {
        students.add(new Student("001", "刘一", 721, true, GradeType.THREE_GRADE));
        students.add(new Student("002", "陈二", 637, true, GradeType.THREE_GRADE));
        students.add(new Student("003", "朱三", 637, true, GradeType.THREE_GRADE));
        students.add(new Student("004", "李四", 531, true, GradeType.TWO_GRADE));
        students.add(new Student("005", "王五", 483, false, GradeType.THREE_GRADE));
        students.add(new Student("006", "赵六", 367, true, GradeType.THREE_GRADE));
        students.add(new Student("007", "孙七", 499, false, GradeType.ONE_GRADE));
        students.add(new Student("008", "向八", 520, false, GradeType.ONE_GRADE));
        students.add(new Student("009", "向八", 520, false, GradeType.ONE_GRADE));
    }
}

二、Collectors方法及使用

1. Collectors.toCollection()

/**
 * Collectors.toCollection()
 * 返回一个Collector收集器,它按遇见顺序将输入元素累积到一个新的Collection收集器中。Collection收集器由提供的工厂创建。
 * 输出:[刘一, 陈二, 朱三, 李四, 王五, 赵六, 孙七, 向八, 向八]
 */
System.out.println(
        students.stream()
                .map(Student::getName)
                .collect((Collector<? super String, Object, LinkedList<Object>>) Collectors.toCollection(LinkedList::new))
);

2. Collectors.toList() / Collectors.toSet()

/**
 * Collectors.toList()  /  Collectors.toSet()
 * 返回一个Collector收集器,它将输入元素累积到一个新的List/Set中。
 * 输出:[刘一, 陈二, 朱三, 李四, 王五, 赵六, 孙七, 向八, 向八]
 */
System.out.println(
        students.stream()
                .map(Student::getName)
                .collect(Collectors.toList())
);

3. Collectors.toMap(Function, Function) / Collectors.toConcurrentMap(Function, Function)

/**
 * Collectors.toMap(Function, Function)  /  Collectors.toConcurrentMap(Function, Function)
 * 返回一个Collector收集器,它将元素累积到Map中,其键和值是将提供的映射函数应用于输入元素的结果。
 * 输出:{001=刘一, 002=陈二, 003=朱三, 004=李四, 005=王五, 006=赵六, 007=孙七, 008=向八, 009=向八}
 */
System.out.println(
        students.stream()
                .collect(Collectors.toMap(Student::getId, Student::getName))
);

4. Collectors.toMap(Function, Function, BinaryOperator) / Collectors.toConcurrentMap(Function, Function, BinaryOperator)

/**
 * Collectors.toMap(Function, Function, BinaryOperator)  /  Collectors.toConcurrentMap(Function, Function, BinaryOperator)
 * 返回一个并发的Collector收集器,它将元素累积到Map中,其键和值是将提供的映射函数应用于输入元素的结果。
 * 如果映射的键包含重复项(根据Object#equals(Object)),则将值映射函数应用于每个相等的元素,并使用提供的合并函数合并结果。
 * 输出:{THREE_GRADE=5, ONE_GRADE=3, TWO_GRADE=1}
 */
System.out.println(
        students.stream()
                .collect(Collectors.toMap(
                        Student::getGradeType,
                        val -> 1,
                        (a, b) -> a + b))
);

5. Collectors.collectingAndThen(Collector, Function)

/**
 * Collectors.collectingAndThen(Collector, Function)
 * collectingAndThen方法调整Collector收集器以执行其它的结束转换。
 * 例如,可以调整toList()收集器,以始终生成一个不可变的列表
 * 输出:[001, 002, 003, 004, 005, 006, 007, 008, 009]
 */
List<String> ids = CollectorsTest.students.stream()
        .map(Student::getId)
        .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
System.out.println(ids);

6. Collectors.joining() / joining(delimiter) / joining(delimiter, prefix, suffix)

/**
 * Collectors.joining()
 * joining()方法返回一个Collector收集器,它按遇见顺序将输入元素连接成String。
 * 输出:001002003004005006007008009
 *
 * joining(delimiter)
 * joining(delimiter)方法返回一个Collector收集器,它以遇见顺序连接由指定分隔符分隔的输入元素。
 * 输出:001,002,003,004,005,006,007,008,009
 *
 * joining(delimiter, prefix, suffix)
 * joining(delimiter, prefix, suffix)方法返回一个Collector收集器,它以遇见顺序将由指定分隔符分隔的输入元素与指定的前缀和后缀连接起来。
 * 输出:ids[001,002,003,004,005,006,007,008,009]
 */
System.out.println(
        CollectorsTest.students.stream()
                .map(Student::getId)
                .collect(Collectors.joining(",", "ids[", "]"))
);

7. Collectors.mapping(Function, Collector)

/**
 * Collectors.mapping(Function, Collector)
 * mapping方法通过在累积之前将映射函数应用于每个输入元素,将Collector收集器接受U类型的元素调整为一个接受T类型的元素。
 * 输出:[001, 002, 003, 004, 005, 006, 007, 008, 009]
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.mapping(Student::getId, Collectors.toList()))
);

8. Collectors.maxBy(Comparator) / Collectors.minBy(Comparator)

/**
 * Collectors.maxBy(Comparator)      /       Collectors.minBy(Comparator)
 * maxBy方法返回一个Collector收集器,它根据给定的Comparator比较器生成 最大/最小 元素,描述为Optional<T>。
 * 输出:Optional[001]      /       Optional[006]
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.maxBy(Comparator.comparingInt(Student::getTotalScore)))
                .map(Student::getId)
);

9. Collectors.counting()

/**
 * Collectors.counting()
 * counting方法返回一个Collector收集器接受T类型的元素,用于计算输入元素的数量。如果没有元素,则结果为0。
 * 输出:9
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.counting())
);

10. Collectors.groupingBy(Function) / groupingByConcurrent(Function)

/**
 * Collectors.groupingBy(Function)   /   groupingByConcurrent(Function)
 * groupingBy(Function)方法返回一个Collector收集器对T类型的输入元素执行"group by"操作,
 * 根据分类函数对元素进行分组,并将结果返回到Map。
 * 结果:Map<K, List<T>>
 * 输出:Map<K, List<T>>
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.groupingBy(Student::getGradeType))
);

11. Collectors.groupingBy(Function, Collector) / groupingByConcurrent(Function, Collector)

/**
 * Collectors.groupingBy(Function, Collector)     /      groupingByConcurrent(Function, Collector)
 * groupingBy(Function)方法返回一个Collector收集器对T类型的输入元素执行"group by"操作,
 * 根据分类函数对元素进行分组,然后使用指定的下游Collector收集器对与给定键关联的值执行缩减操作。
 * 输出:{THREE_GRADE=5, ONE_GRADE=3, TWO_GRADE=1}
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.groupingBy(Student::getGradeType, Collectors.counting()))
);

12. Collectors.groupingBy(Function, Supplier, Collector) / groupingByConcurrent(Function, Supplier, Collector)

/**
 * Collectors.groupingBy(Function, Supplier, Collector)     /     groupingByConcurrent(Function, Supplier, Collector)
 * groupingBy(Function, Supplier, Collector)方法返回一个Collector收集器,
 * 对T类型的输入元素执行级联"group by"操作,根据分类函数对元素进行分组,
 * 然后使用指定的下游Collector收集器对与给定键关联的值执行缩减操作。
 * 收集器生成的Map是使用提供的工厂函数Supplier创建的。
 * 输出:{ONE_GRADE=3, TWO_GRADE=1, THREE_GRADE=5}
 */
TreeMap<GradeType, Long> collect = CollectorsTest.students.stream()
        .collect(Collectors.groupingBy(
                Student::getGradeType,
                TreeMap::new,
                Collectors.counting()));
System.out.println(collect);

13. Collectors.summingDouble(ToDoubleFunction) / Collectors.summingInt(ToIntFunction) / Collectors.summingLong(ToLongFunction)

/**
 * Collectors.summingDouble(ToDoubleFunction)
 * Collectors.summingInt(ToIntFunction)
 * Collectors.summingLong(ToLongFunction)
 * 返回一个Collector收集器,它生成应用于输入元素的double/int/long值函数的总和。如果没有元素,则结果为0。
 * 输出:4915.0
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.summingDouble(Student::getTotalScore))
);

14. Collectors.averagingDouble(ToDoubleFunction) / Collectors.averagingInt(ToIntFunction) / Collectors.averagingLong(ToLongFunction)

/**
 * Collectors.averagingDouble(ToDoubleFunction)
 * Collectors.averagingInt(ToIntFunction)
 * Collectors.averagingLong(ToLongFunction)
 * averagingDouble方法返回一个Collector收集器,它生成应用于输入元素的double/int/long值函数的算术平均值。如果没有元素,则结果为0。
 * 输出:546.1111111111111
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.averagingDouble(Student::getTotalScore))
);

15. Collectors.partitioningBy(Predicate)

/**
 * Collectors.partitioningBy(Predicate)
 * partitioningBy(Predicate)方法返回一个Collector收集器,它根据Predicate对输入元素进行分区,并将它们组织成Map<Boolean, List<T>>
 * 输出:Map<Boolean, List<T>>
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.partitioningBy(Student::isLocal))
);

16. Collectors.partitioningBy(Predicate, Collector)

/**
 * Collectors.partitioningBy(Predicate, Collector)
 * partitioningBy(Predicate, Collector)方法返回一个Collector收集器,它根据Predicate对输入元素进行分区,
 * 根据另一个Collector收集器减少每个分区中的值,并将它们组织成Map<Boolean, D>,其值是下游减少的结果。
 * 输出:{false=4, true=5}
 */
System.out.println(
        CollectorsTest.students.stream()
                .collect(Collectors.partitioningBy(Student::isLocal, Collectors.counting()))
);

三、完整代码

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class CollectorsTest {
    private static final List<Student> students = new ArrayList<>(16);

    static {
        students.add(new Student("001", "刘一", 721, true, GradeType.THREE_GRADE));
        students.add(new Student("002", "陈二", 637, true, GradeType.THREE_GRADE));
        students.add(new Student("003", "朱三", 637, true, GradeType.THREE_GRADE));
        students.add(new Student("004", "李四", 531, true, GradeType.TWO_GRADE));
        students.add(new Student("005", "王五", 483, false, GradeType.THREE_GRADE));
        students.add(new Student("006", "赵六", 367, true, GradeType.THREE_GRADE));
        students.add(new Student("007", "孙七", 499, false, GradeType.ONE_GRADE));
        students.add(new Student("008", "向八", 520, false, GradeType.ONE_GRADE));
        students.add(new Student("009", "向八", 520, false, GradeType.ONE_GRADE));
    }

    public static void main(String[] args) {
        /**
         * Collectors.toCollection()
         * 返回一个Collector收集器,它按遇见顺序将输入元素累积到一个新的Collection收集器中。Collection收集器由提供的工厂创建。
         * 输出:[刘一, 陈二, 朱三, 李四, 王五, 赵六, 孙七, 向八, 向八]
         */
        System.out.println(
                students.stream()
                        .map(Student::getName)
                        .collect((Collector<? super String, Object, LinkedList<Object>>) Collectors.toCollection(LinkedList::new))
        );

        /**
         * Collectors.toList()  /  Collectors.toSet()
         * 返回一个Collector收集器,它将输入元素累积到一个新的List/Set中。
         * 输出:[刘一, 陈二, 朱三, 李四, 王五, 赵六, 孙七, 向八, 向八]
         */
        System.out.println(
                students.stream()
                        .map(Student::getName)
                        .collect(Collectors.toList())
        );

        /**
         * Collectors.toMap(Function, Function)  /  Collectors.toConcurrentMap(Function, Function)
         * 返回一个Collector收集器,它将元素累积到Map中,其键和值是将提供的映射函数应用于输入元素的结果。
         * 输出:{001=刘一, 002=陈二, 003=朱三, 004=李四, 005=王五, 006=赵六, 007=孙七, 008=向八, 009=向八}
         */
        System.out.println(
                students.stream()
                        .collect(Collectors.toMap(Student::getId, Student::getName))
        );

        /**
         * Collectors.toMap(Function, Function, BinaryOperator)  /  Collectors.toConcurrentMap(Function, Function, BinaryOperator)
         * 返回一个并发的Collector收集器,它将元素累积到Map中,其键和值是将提供的映射函数应用于输入元素的结果。
         * 如果映射的键包含重复项(根据Object#equals(Object)),则将值映射函数应用于每个相等的元素,并使用提供的合并函数合并结果。
         * 输出:{THREE_GRADE=5, ONE_GRADE=3, TWO_GRADE=1}
         */
        System.out.println(
                students.stream()
                        .collect(Collectors.toMap(
                                Student::getGradeType,
                                val -> 1,
                                (a, b) -> a + b))
        );

        /**
         * Collectors.collectingAndThen(Collector, Function)
         * collectingAndThen方法调整Collector收集器以执行其它的结束转换。
         * 例如,可以调整toList()收集器,以始终生成一个不可变的列表
         * 输出:[001, 002, 003, 004, 005, 006, 007, 008, 009]
         */
        List<String> ids = CollectorsTest.students.stream()
                .map(Student::getId)
                .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
        System.out.println(ids);

        /**
         * Collectors.joining()
         * joining()方法返回一个Collector收集器,它按遇见顺序将输入元素连接成String。
         * 输出:001002003004005006007008009
         *
         * joining(delimiter)
         * joining(delimiter)方法返回一个Collector收集器,它以遇见顺序连接由指定分隔符分隔的输入元素。
         * 输出:001,002,003,004,005,006,007,008,009
         *
         * joining(delimiter, prefix, suffix)
         * joining(delimiter, prefix, suffix)方法返回一个Collector收集器,它以遇见顺序将由指定分隔符分隔的输入元素与指定的前缀和后缀连接起来。
         * 输出:ids[001,002,003,004,005,006,007,008,009]
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .map(Student::getId)
                        .collect(Collectors.joining(",", "ids[", "]"))
        );

        /**
         * Collectors.mapping(Function, Collector)
         * mapping方法通过在累积之前将映射函数应用于每个输入元素,将Collector收集器接受U类型的元素调整为一个接受T类型的元素。
         * 输出:[001, 002, 003, 004, 005, 006, 007, 008, 009]
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.mapping(Student::getId, Collectors.toList()))
        );

        /**
         * Collectors.maxBy(Comparator)      /       Collectors.minBy(Comparator)
         * maxBy方法返回一个Collector收集器,它根据给定的Comparator比较器生成 最大/最小 元素,描述为Optional<T>。
         * 输出:Optional[001]      /       Optional[006]
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.maxBy(Comparator.comparingInt(Student::getTotalScore)))
                        .map(Student::getId)
        );

        /**
         * Collectors.counting()
         * counting方法返回一个Collector收集器接受T类型的元素,用于计算输入元素的数量。如果没有元素,则结果为0。
         * 输出:9
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.counting())
        );

        /**
         * Collectors.groupingBy(Function)   /   groupingByConcurrent(Function)
         * groupingBy(Function)方法返回一个Collector收集器对T类型的输入元素执行"group by"操作,
         * 根据分类函数对元素进行分组,并将结果返回到Map。
         * 结果:Map<K, List<T>>
         * 输出:Map<K, List<T>>
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.groupingBy(Student::getGradeType))
        );

        /**
         * Collectors.groupingBy(Function, Collector)     /      groupingByConcurrent(Function, Collector)
         * groupingBy(Function)方法返回一个Collector收集器对T类型的输入元素执行"group by"操作,
         * 根据分类函数对元素进行分组,然后使用指定的下游Collector收集器对与给定键关联的值执行缩减操作。
         * 输出:{THREE_GRADE=5, ONE_GRADE=3, TWO_GRADE=1}
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.groupingBy(Student::getGradeType, Collectors.counting()))
        );

        /**
         * Collectors.groupingBy(Function, Supplier, Collector)     /     groupingByConcurrent(Function, Supplier, Collector)
         * groupingBy(Function, Supplier, Collector)方法返回一个Collector收集器,
         * 对T类型的输入元素执行级联"group by"操作,根据分类函数对元素进行分组,
         * 然后使用指定的下游Collector收集器对与给定键关联的值执行缩减操作。
         * 收集器生成的Map是使用提供的工厂函数Supplier创建的。
         * 输出:{ONE_GRADE=3, TWO_GRADE=1, THREE_GRADE=5}
         */
        TreeMap<GradeType, Long> collect = CollectorsTest.students.stream()
                .collect(Collectors.groupingBy(
                        Student::getGradeType,
                        TreeMap::new,
                        Collectors.counting()));
        System.out.println(collect);

        /**
         * Collectors.summingDouble(ToDoubleFunction)
         * Collectors.summingInt(ToIntFunction)
         * Collectors.summingLong(ToLongFunction)
         * 返回一个Collector收集器,它生成应用于输入元素的double/int/long值函数的总和。如果没有元素,则结果为0。
         * 输出:4915.0
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.summingDouble(Student::getTotalScore))
        );

        /**
         * Collectors.averagingDouble(ToDoubleFunction)
         * Collectors.averagingInt(ToIntFunction)
         * Collectors.averagingLong(ToLongFunction)
         * averagingDouble方法返回一个Collector收集器,它生成应用于输入元素的double/int/long值函数的算术平均值。如果没有元素,则结果为0。
         * 输出:546.1111111111111
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.averagingDouble(Student::getTotalScore))
        );

        /**
         * Collectors.partitioningBy(Predicate)
         * partitioningBy(Predicate)方法返回一个Collector收集器,它根据Predicate对输入元素进行分区,并将它们组织成Map<Boolean, List<T>>
         * 输出:Map<Boolean, List<T>>
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.partitioningBy(Student::isLocal))
        );

        /**
         * Collectors.partitioningBy(Predicate, Collector)
         * partitioningBy(Predicate, Collector)方法返回一个Collector收集器,它根据Predicate对输入元素进行分区,
         * 根据另一个Collector收集器减少每个分区中的值,并将它们组织成Map<Boolean, D>,其值是下游减少的结果。
         * 输出:{false=4, true=5}
         */
        System.out.println(
                CollectorsTest.students.stream()
                        .collect(Collectors.partitioningBy(Student::isLocal, Collectors.counting()))
        );
    }
}