将流的元素收集到集合中
集合 toList() 和 toSet()
通过使用 Stream.collect 操作,可以很容易地将 Stream 中的元素收集到容器中 : 
System.out.println(Arrays
    .asList("apple", "banana", "pear", "kiwi", "orange")
    .stream()
    .filter(s -> s.contains("a"))
    .collect(Collectors.toList())
);
// prints: [apple, banana, pear, orange]
其他集合实例,例如 Set ,可以使用其他 Collectors 内置方法制作。例如, Collectors.toSet() 将 Stream 的元素收集到 Set 中 。
明确控制 List 或 Set 的实施 
根据 Collectors#toList() 和 Collectors#toSet() 的文档,对于返回的 List或 Set的类型,可变性,可串行性或线程安全性没有任何保证。
为了显式控制要返回的实现,可以使用 Collectors#toCollection(Supplier) ,而给定的供应商返回一个新的空集合。
// syntax with method reference
System.out.println(strings
        .stream()
        .filter(s -> s != null && s.length() <= 3)
        .collect(Collectors.toCollection(ArrayList::new))
);
// syntax with lambda
System.out.println(strings
        .stream()
        .filter(s -> s != null && s.length() <= 3)
        .collect(Collectors.toCollection(() -> new LinkedHashSet<>()))
);
使用 toMap 收集元素
收集器将元素累积到 Map 中,其中 key 是 Student Id,Value 是 Student Value。
  List<Student> students = new ArrayList<Student>(); 
    students.add(new Student(1,"test1"));
    students.add(new Student(2,"test2"));
    students.add(new Student(3,"test3"));
    
    Map<Integer, String> IdToName = students.stream()
        .collect(Collectors.toMap(Student::getId, Student::getName));
    System.out.println(IdToName);
输出:
{1=test1, 2=test2, 3=test3}
Collectors.toMap 有另一个实现方式。如果在列表中添加 Map 中的新成员时重复键,mergeFunction 主要用于选择新值或保留旧值。
mergeFunction 通常看起来像:(s1, s2) -> s1 保留对应于重复键的值,或者 (s1, s2) -> s2 为重复键设置新值。
将元素收集到集合的映射
示例:从 ArrayList 到 Map <String,List <>>
通常需要从主列表中制作列表地图。示例:从列表中的学生,我们需要为每个学生制作一个主题列表的地图。
    List<Student> list = new ArrayList<>();
    list.add(new Student("Davis", SUBJECT.MATH, 35.0));
    list.add(new Student("Davis", SUBJECT.SCIENCE, 12.9));
    list.add(new Student("Davis", SUBJECT.GEOGRAPHY, 37.0));
    list.add(new Student("Sascha", SUBJECT.ENGLISH, 85.0));
    list.add(new Student("Sascha", SUBJECT.MATH, 80.0));
    list.add(new Student("Sascha", SUBJECT.SCIENCE, 12.0));
    list.add(new Student("Sascha", SUBJECT.LITERATURE, 50.0));
    list.add(new Student("Robert", SUBJECT.LITERATURE, 12.0));
    Map<String, List<SUBJECT>> map = new HashMap<>();
    list.stream().forEach(s -> {
                map.computeIfAbsent(s.getName(), x -> new ArrayList<>()).add(s.getSubject());
            });
    System.out.println(map);
输出:
{ Robert=[LITERATURE], 
Sascha=[ENGLISH, MATH, SCIENCE, LITERATURE], 
Davis=[MATH, SCIENCE, GEOGRAPHY] }
示例:从 ArrayList 到 Map <String,Map <>>
    List<Student> list = new ArrayList<>();
    list.add(new Student("Davis", SUBJECT.MATH, 1, 35.0));
    list.add(new Student("Davis", SUBJECT.SCIENCE, 2, 12.9));
    list.add(new Student("Davis", SUBJECT.MATH, 3, 37.0));
    list.add(new Student("Davis", SUBJECT.SCIENCE, 4, 37.0));
    list.add(new Student("Sascha", SUBJECT.ENGLISH, 5, 85.0));
    list.add(new Student("Sascha", SUBJECT.MATH, 1, 80.0));
    list.add(new Student("Sascha", SUBJECT.ENGLISH, 6, 12.0));
    list.add(new Student("Sascha", SUBJECT.MATH, 3, 50.0));
    list.add(new Student("Robert", SUBJECT.ENGLISH, 5, 12.0));
    Map<String, Map<SUBJECT, List<Double>>> map = new HashMap<>();
    list.stream().forEach(student -> {
        map.computeIfAbsent(student.getName(), s -> new HashMap<>())
                .computeIfAbsent(student.getSubject(), s -> new ArrayList<>())
                .add(student.getMarks());
    });
    System.out.println(map);
输出:
{ Robert={ENGLISH=[12.0]}, 
Sascha={MATH=[80.0, 50.0], ENGLISH=[85.0, 12.0]}, 
Davis={MATH=[35.0, 37.0], SCIENCE=[12.9, 37.0]} }
备忘单
| 目标 | 码 | 
|---|---|
| 集合到 List | Collectors.toList() | 
| 集合预先分配的 ArrayList | Collectors.toCollection(() -> new ArrayList<>(size)) | 
| 集合到 Set | Collectors.toSet() | 
| 集合到具有更好迭代性能的 Set | Collectors.toCollection(() -> new LinkedHashSet<>()) | 
| 集合一个不区分大小写的 Set<String> | Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)) | 
| 集合到 EnumSet<AnEnum>(枚举的最佳表现) | Collectors.toCollection(() -> EnumSet.noneOf(AnEnum.class)) | 
| 使用独特的键集合到 Map<K,V> | Collectors.toMap(keyFunc,valFunc) | 
| 将 MyObject.getter()映射到唯一的 MyObject | Collectors.toMap(MyObject::getter, Function.identity()) | 
| 将 MyObject.getter()映射到多个 MyObjects | Collectors.groupingBy(MyObject::getter) |