Java将流中的元素收集到集合中

示例

用toList()和收集toSet()

Stream通过使用以下Stream.collect操作,可以轻松将a中的元素收集到容器中:

System.out.println(Arrays
    .asList("apple", "banana", "pear", "kiwi", "orange")
    .stream()
    .filter(s -> s.contains("a"))
    .collect(Collectors.toList())
);
// 印刷品:[苹果,香蕉,梨,橙]

Set可以使用其他Collectors内置方法来创建其他集合实例,例如。例如,将a的元素收集到中。Collectors.toSet()StreamSet


明确控制List或的实施Set

据文件和,还有的类型,可变性,串行化,或线程安全性无法保证或退回。Collectors#toList()Collectors#toSet()ListSet

为了明确控制要返回的实现,可以使用给定的供应商返回一个新的空集合的替代方法。Collectors#toCollection(Supplier)

// 方法参考的语法
System.out.println(strings
        .stream()
        .filter(s -> s != null && s.length() <= 3)
        .collect(Collectors.toCollection(ArrayList::new))
);

// lambda的语法
System.out.println(strings
        .stream()
        .filter(s -> s != null && s.length() <= 3)
        .collect(Collectors.toCollection(() -> new LinkedHashSet<>()))
);

使用toMap收集元素

收集器将元素累积到Map中,其中键是学生ID,值是学生值。

  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另一个实现Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction)。如果在列表中的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]} }

备忘单

目标
收集到 ListCollectors.toList()
收集到ArrayList预先分配的大小Collectors.toCollection(() -> new ArrayList<>(size))
收集到 SetCollectors.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)
映射到唯一的MyObjectMyObject.getter()Collectors.toMap(MyObject::getter, Function.identity())
映射到多个MyObjectsMyObject.getter()Collectors.groupingBy(MyObject::getter)