跳至主要內容

结果收集

Mr.Hope...大约 5 分钟

1. 收集到集合中

public static void main(String[] args) {
    // Stream<String> stream = Stream.of("aa", "bb", "cc");
    List<String> list = Stream.of("aa", "bb", "cc", "aa")
            .collect(Collectors.toList());
    System.out.println(list);
    // 收集到 Set集合中
    Set<String> set = Stream.of("aa", "bb", "cc", "aa")
            .collect(Collectors.toSet());
    System.out.println(set);
    // 如果需要获取的类型为具体的实现,比如:ArrayList HashSet
    ArrayList<String> arrayList = Stream.of("aa", "bb", "cc", "aa")
            .collect(Collectors.toCollection(ArrayList::new));
    System.out.println(arrayList);
    HashSet<String> hashSet = Stream.of("aa", "bb", "cc", "aa")
            .collect(Collectors.toCollection(HashSet::new));
    System.out.println(hashSet);
}

Output:

[aa, bb, cc, aa]
[aa, bb, cc]
[aa, bb, cc, aa]
[aa, bb, cc]

2. 收集到数组中

Stream中提供了toArray方法来将结果放到一个数组中,返回值类型是Object[],如果我们要指定返回的类型,那么可以使用另一个重载的toArray(IntFunction f)方法

public static void main(String[] args) {
    Object[] objects = Stream.of("aa", "bb", "cc", "aa")
            .toArray(); // 返回的数组中的元素是 Object类型
    System.out.println(Arrays.toString(objects));
    // 如果我们需要指定返回的数组中的元素类型
    String[] strings = Stream.of("aa", "bb", "cc", "aa")
            .toArray(String[]::new);
    System.out.println(Arrays.toString(strings));
}

3. 聚合计算

当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作,比如获得最大值,最小值,求和,平均值,统计数量

public static void main(String[] args) {
    // 获取年龄的最大值
    Optional<Person> maxAge = Stream.of(
            new Person("张三", 18)
            , new Person("李四", 22)
            , new Person("张三", 13)
            , new Person("王五", 15)
            , new Person("张三", 19)
    ).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge()));
    System.out.println("最大年龄:" + maxAge.get());
    // 获取年龄的最小值
    Optional<Person> minAge = Stream.of(
            new Person("张三", 18)
            , new Person("李四", 22)
            , new Person("张三", 13)
            , new Person("王五", 15)
            , new Person("张三", 19)
    ).collect(Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge()));
    System.out.println("最新年龄:" + minAge.get());
    // 求所有人的年龄之和
    Integer sumAge = Stream.of(
                    new Person("张三", 18)
                    , new Person("李四", 22)
                    , new Person("张三", 13)
                    , new Person("王五", 15)
                    , new Person("张三", 19)
            )
            .collect(Collectors.summingInt(Person::getAge));
    System.out.println("年龄总和:" + sumAge);
    // 年龄的平均值
    Double avgAge = Stream.of(
            new Person("张三", 18)
            , new Person("李四", 22)
            , new Person("张三", 13)
            , new Person("王五", 15)
            , new Person("张三", 19)
    ).collect(Collectors.averagingInt(Person::getAge));
    System.out.println("年龄的平均值:" + avgAge);
    // 统计数量
    Long count = Stream.of(
                    new Person("张三", 18)
                    , new Person("李四", 22)
                    , new Person("张三", 13)
                    , new Person("王五", 15)
                    , new Person("张三", 19)
            ).filter(p->p.getAge() > 18)
            .collect(Collectors.counting());
    System.out.println("满足条件的记录数:" + count);
}

Output:

最大年龄:Person(name=李四, age=22, height=null)
最新年龄:Person(name=张三, age=13, height=null)
年龄总和:87
年龄的平均值:17.4
满足条件的记录数:2

4. 分组操作

public static void main(String[] args) {
        // 根据账号对数据进行分组
        Map<String, List<Person>> map1 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.groupingBy(Person::getName));
        map1.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));
        System.out.println("-----------");
        // 根据年龄分组 如果大于等于18 成年否则未成年
        Map<String, List<Person>> map2 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.groupingBy(p->p.getAge() >= 18?"成年":"未成年"));
        map2.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));
    }

Output:

k=李四	v=[Person(name=李四, age=22, height=177), Person(name=李四, age=15, height=166)]
k=张三	v=[Person(name=张三, age=18, height=175), Person(name=张三, age=14, height=165), Person(name=张三, age=19, height=182)]
-----------
k=未成年	v=[Person(name=张三, age=14, height=165), Person(name=李四, age=15, height=166)]
k=成年	v=[Person(name=张三, age=18, height=175), Person(name=李四, age=22, height=177), Person(name=张三, age=19, height=182)]
多级分组:

先根据name分组然后根据年龄分组

public static void main(String[] args) {
    // 根据账号对数据进行分组
    Map<String, Map<String,List<Person>>> map1 = Stream.of(
            new Person("张三", 18, 175)
            , new Person("李四", 22, 177)
            , new Person("张三", 14, 165)
            , new Person("李四", 15, 166)
            , new Person("张三", 19, 182)
    ).collect(Collectors.groupingBy(Person::getName,
            Collectors.groupingBy(p->p.getAge() >= 18?"成年":"未成年")));
    map1.forEach((k,v)->{
        System.out.println(k);
        v.forEach((k1,v1)-> System.out.println("\t"+k1 + "=" + v1));
    });
}

Output:

李四
	未成年=[Person(name=李四, age=15, height=166)]
	成年=[Person(name=李四, age=22, height=177)]
张三
	未成年=[Person(name=张三, age=14, height=165)]
	成年=[Person(name=张三, age=18, height=175), Person(name=张三, age=19, height=182)]

5. 分区操作

Collectors.partitioningBy会根据值是否为true,把集合中的数据分割为两个列表,一个true列表,一个 false列表

image-20240415105641494
public static void main(String[] args) {
    // 根据账号对数据进行分组
     Stream.of(
            new Person("张三", 18, 175)
            , new Person("李四", 22, 177)
            , new Person("张三", 14, 165)
            , new Person("李四", 15, 166)
            , new Person("张三", 19, 182)
    ).collect(Collectors.partitioningBy(p->p.getAge()>18))
             .forEach((k,v)-> System.out.println(k+"\t" + v));
}

Output

false	[Person(name=张三, age=18, height=175), Person(name=张三, age=14, height=165), Person(name=李四, age=15, height=166)]
true	[Person(name=李四, age=22, height=177), Person(name=张三, age=19, height=182)]

6. 数据拼接

Collectors.joining会根据指定的连接符,将所有的元素连接成一个字符串

public static void main(String[] args) {
    String s1 = Stream.of(
                    new Person("张三", 18, 175)
                    , new Person("李四", 22, 177)
                    , new Person("张三", 14, 165)
                    , new Person("李四", 15, 166)
                    , new Person("张三", 19, 182)
            ).map(Person::getName)
            .collect(Collectors.joining());
    // 张三李四张三李四张三
    System.out.println(s1);
    String s2 = Stream.of(
                    new Person("张三", 18, 175)
                    , new Person("李四", 22, 177)
                    , new Person("张三", 14, 165)
                    , new Person("李四", 15, 166)
                    , new Person("张三", 19, 182)
            ).map(Person::getName)
            .collect(Collectors.joining("_"));
    // 张三_李四_张三_李四_张三
    System.out.println(s2);
    String s3 = Stream.of(
                    new Person("张三", 18, 175)
                    , new Person("李四", 22, 177)
                    , new Person("张三", 14, 165)
                    , new Person("李四", 15, 166)
                    , new Person("张三", 19, 182)
            ).map(Person::getName)
            .collect(Collectors.joining("_", "###", "$$$"));
    // ###张三_李四_张三_李四_张三$$$
    System.out.println(s3);
}

Output:

张三李四张三李四张三
张三_李四_张三_李四_张三
###张三_李四_张三_李四_张三$$$

提示

suffix public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, CharSequence prefix,CharSequence suffix) delimiter:是连接符,表示用delimiter将流中的元素连接起来。

prefix:是在结果字符串的开头添加的字符串,表示在连接后的结果字符串之前加上prefix

suffix:是在结果字符串的结尾添加的字符串,表示在连接后的结果字符串之后加上suffix。