Java8Stream 流的使用

Java8 Stream流

文章目录

    • Java8 Stream流
        • 一、 Stream 概述
        • 二、 Stream 的创建
          • 1. 通过 `java.util.Collection.stream()` 方法用集合创建流
          • 2. 使用`java.util.Arrays.stream(T[] array)`方法用数组创建流
          • 3. 使用`Stream`的静态方法:`of()、iterate()、generate()`
          • 4. 顺序流和并行流的简单区分
        • 三、Stream 的使用
          • 1. 遍历、匹配(foreach、find、match)
          • 2. 筛选(filter)
          • 3. 聚合(max、min、count)
          • 4. 映射(map/flatMap)
          • 5. 归约(reduce)
          • 6. 收集-分组(collect-groupBy)
          • 7. 收集-分区(collect-partitioningBy)
          • 8. 收集-归集(toList/toSet/toMap)
          • 9. 收集-统计(collect-count/averaging/maxBy/summing/summarizing)
          • 10. 收集-结合(collect-joining)
          • 11. 收集-规约(collect-reduce)
          • 11. 排序(sorted)
          • 12. 提取、组合(concat/distinct/limit/skip)
        • 四、 项目地址

Java8Stream 流的使用_第1张图片
文章图片参考与网络,侵权必删.

一、 Stream 概述

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

Stream 可以由数组或者集合创建,对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个。
  2. 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或者值。

Stream 的特性:

  1. Stream 不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
  2. Stream 不会改变数据源,通常情况下会产生一个新的集合或一个值。
  3. Stream 具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

二、 Stream 的创建

Stream 可以通过集合或者数组进行创建

1. 通过 java.util.Collection.stream() 方法用集合创建流
List<String> list = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();
2. 使用java.util.Arrays.stream(T[] array)方法用数组创建流
int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);
3. 使用Stream的静态方法:of()、iterate()、generate()
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

输出结果:

0 3 6 9
0.6796156909271994
0.1914314208854283
0.8116932592396652

4. 顺序流和并行流的简单区分

Stream 是顺序流,由主线程按顺序对流执行操作;

parallelStream 是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。

例如筛选集合中的奇数,两者的处理不同之处:

Java8Stream 流的使用_第2张图片

由图可以看出,并行流类似于二分查找,如果流中的数据量足够大,并行流可以加快处理速度。

除了直接创建并行流,还可以通过 parallel 把顺序流转换成并行流:

Optional<Integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();

三、Stream 的使用

下面代码使用到的类:

/**
 * @packageName: com.lzhch.stream.lambda.init
 * @className: Person
 * @description: 用户类
 * @version: v1.0
 * @author: lzhch
 * @date: 2021-12-01 16:15
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    private String name;

    private String sex;

    private int age;

    private int salary;

    private String address;

}
/**
 * @packageName: com.lzhch.stream.lambda.init
 * @className: InitList
 * @description:  初始化列表
 * @version: v1.0
 * @author: lzhch
 * @date: 2021-12-01 16:14
 */
public class InitList {

    public static List<Person> initList() {
        List<Person> resList = new ArrayList<>();
        resList.add(new Person("xxx", "man", 20, 9, "address1"));
        resList.add(new Person("yyy", "man", 22, 10, "address2"));
        resList.add(new Person("zzz", "women", 40, 15, "address3"));
        resList.add(new Person("aaa", "women", 60, 6, "address4"));

        return resList;
    }

}
1. 遍历、匹配(foreach、find、match)

Stream 也是支持类似集合的遍历和元素匹配的,只是 Stream 中的元素是以 Optional 类型存在的。

Java8Stream 流的使用_第3张图片

		/**
     * foreach/ stream.foreach
     * foreach 循环的入参是一个 Consumer 类型, 是函数式接口
     * foreach 和 stream.foreach 的效果是一样的
     * foreach 循环更加适合用于简单逻辑的循环遍历(或修改), 不适合进行过多的复杂业务的处理
     */
    public void foreach() {
        List<Person> list = InitList.initList();
        System.out.println("========foreach=======");
        list.forEach(x -> System.out.println(x.toString()));

        System.out.println("========stream.foreach=======");
        list.stream().forEach(x -> System.out.println(x.toString()));

        System.out.println("========foreach complex=======");
        list.stream().forEach(x -> {
            if ("xxx".equals(x.getName())) {
                System.out.println(x.toString());
            }
        });

        list.stream().forEach(x -> x.setAge(10));
        System.out.println(list.toString());
    }
    /**
     * find
     * findFirst 匹配第一个元素
     * findAny 匹配任意一个元素, 适合并行流, 也可以跟 filter 等搭配使用
     */
    public void find() {
        List<Person> list = InitList.initList();
        System.out.println("========find first=======");
        Optional<Person> first = list.stream().findFirst();
        Person person = list.stream().findFirst().orElse(null);
        System.out.println("first :{} " + first.get().toString());

        System.out.println("========find any=======");
        Optional<Person> any = list.parallelStream().findAny();
        System.out.println("any :{} " + any.get().toString());
        Optional<Person> anyFilter = list.parallelStream().filter(x -> x.getAge() > 20).findAny();
        System.out.println("any :{} " + anyFilter.get().toString());
    }
    /**
     * match
     * 根据条件进行匹配 返回 boolean 类型
     * allMatch: list 的元素全部满足条件返回 true; 反之 返回 false
     * anyMatch: list 的元素任意一个满足条件返回 true; 反之 返回 false
     * noneMatch: list 的元素全部不满足条件返回 true; 反之 返回 false
     */
    public void match() {
        List<Person> list = InitList.initList();
        System.out.println("========all match=======");
        boolean allMatch = list.stream().allMatch(x -> x.getAge() > 40);
        System.out.println("allMatch :{} " + allMatch);

        System.out.println("========any match=======");
        boolean anyMatch = list.stream().anyMatch(x -> x.getAge() > 70);
        System.out.println("anyMatch :{} " + anyMatch);

        System.out.println("========none match=======");
        boolean noneMatch = list.stream().noneMatch(x -> x.getAge() > 50);
        System.out.println("noneMatch :{} " + noneMatch);
    }
2. 筛选(filter)

筛选是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

Java8Stream 流的使用_第4张图片

    /**
     * stream.filter
     * filter 是将符合条件的元素过滤出来形成新的流 所以需要新的集合去接收返回值
     */
    public void filter() {
        List<Person> list = InitList.initList();
        System.out.println("========filter=======");
        List<Person> resList = list.stream().filter(x -> x.getAge() > 24).collect(Collectors.toList());
        System.out.println("old list :{} " + list.toString());
        System.out.println("resList :{} " + resList);

        System.out.println("========filter foreach======");
        list.stream().filter(x -> x.getAge() > 24).forEach(System.out::println);

        System.out.println("======== filter findFirst ========");
        Optional<Person> first = list.stream().filter(x -> x.getAge() > 30).findFirst();
        System.out.println("filter findFirst :{} " + first);

        System.out.println("======== filter findAny =======");
        Optional<Person> any = list.stream().filter(x -> x.getAge() > 30).findAny();
        System.out.println("findAny :{} " + any);
    }
3. 聚合(max、min、count)

Java8Stream 流的使用_第5张图片

    /**
     * 聚合(max/min/count)
     */
    public void aggregate() {
        List<Person> list = InitList.initList();
        System.out.println("======== max age ========");
        Optional<Person> max = list.stream().max(Comparator.comparingInt(Person::getAge));
        System.out.println("max :{} " + max.get());

        System.out.println("======== min age ========");
        Optional<Person> min = list.stream().min(Comparator.comparing(Person::getAge));
        System.out.println("min :{} " + min.get());

        System.out.println("======== count ========");
        long count = list.stream().filter(x -> x.getAge() > 20).count();
        System.out.println("count :{age > 20} " + count);
    }
4. 映射(map/flatMap)

映射可以将一个流的元素按照一定的规则映射到另一个流中,分为 mapflatMap

  • map: 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap: 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

Java8Stream 流的使用_第6张图片

    /**
     * 映射(map/flatMap)
     * 映射, 可以将一个流的元素按照一定的映射规则映射到另一个流中
     * map: 接收一个有返回值的函数作为参数, 该函数会被应用到每个元素上, 并将其映射成一个新的元素
     * flatMap: 接收一个有返回值的函数作为参数, 将流中的每个值都换成另一个流, 然后把所有流连接成一个流
     */
    public void mapping() {
        List<Person> list = InitList.initList();

        // 会改变原有集合的值
        System.out.println("======== map 会改变原有集合的值 =======");
        System.out.println("original list :{} " + list.toString());
        // 新建一个 list 统一修改新的 list 的 address 字段为 '这是一个地址', 会修改原有的 list 的值 可以用原有的 list 去接收
        List<Person> newList = list.stream()
                .map(x -> {
                    x.setAge(10);
                    return x;
                })
                .collect(Collectors.toList());
        System.out.println("new list :{} " + newList.toString());

        // 不改变原有集合的值
        System.out.println("======== map 不改变原有集合的值 =======");
        list = InitList.initList();
        System.out.println("original list :{} " + list.toString());
        // 新建一个 list 统一修改新的 list 的 address 字段为 '这是一个地址', 不会修改原有的 list 的值 需要用新的 list 去接收
        List<Person> newList1 = list.stream()
                .map(x -> {
                    Person person = new Person();
                    BeanUtils.copyProperties(x, person);
                    person.setAddress("这是一个地址");
                    return person;
                })
                .collect(Collectors.toList());
        System.out.println("new list :{} " + newList1.toString());

        // map 可以返回不同类型的 list(可用于类型转换)
        System.out.println("======== map 返回不同类型的 list(可用于类型转换) =======");
        list = InitList.initList();
        System.out.println("original list :{} " + list.toString());
        // 将 list 中的 name 属性提取成一个单独的 list
        // List newList3 = list.stream()
        //         .map(x -> {
        //             String person = x.getName();
        //             return person;
        //         })
        //         .collect(Collectors.toList());
        List<String> newList3 = list.stream()
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println("new list :{} " + newList3.toString());

        System.out.println("======== 分组后拼接成字符串 =============");
        list = InitList.initList();
        System.out.println("original list :{} " + list.toString());
        String collect = list.stream().map(Person::getName).collect(Collectors.joining(","));
        System.out.println("new String :{} " + collect);

        System.out.println("======== flatMap =======");
        List<String> list1 = Arrays.asList("m-k-l-a", "1-3-5-7");
        List<String> listNew = list1.stream().flatMap(s -> {
            // 将每个元素转换成一个stream
            String[] split = s.split("-");
            Stream<String> s2 = Arrays.stream(split);
            return s2;
        }).collect(Collectors.toList());

        System.out.println("处理前的集合:" + list1);
        System.out.println("处理后的集合:" + listNew);
    }
5. 归约(reduce)

归约也称缩减,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

Java8Stream 流的使用_第7张图片

    /**
     *  归约(reduce)
     *      也称缩减, 顾名思义, 是把一个流缩减成一个值, 能实现对集合求和、求乘积和求最值操作
     */
    public void reduce() {
        List<Person> list = InitList.initList();
        System.out.println("======== reduce + ========");
        Optional<Integer> reduce = list.stream().map(x -> x.getAge()).reduce((x, y) -> x + y);
        Optional<Integer> reduce1 = list.stream().map(Person::getAge).reduce(Integer::sum);
        Integer reduce2 = list.stream().map(Person::getAge).reduce(0, Integer::sum);
        System.out.println("reduce :{} " + reduce.get());
        System.out.println("reduce1 :{} " + reduce1.get());
        System.out.println("reduce2 :{} " + reduce1.get());

        System.out.println("======== reduce * ========");
        Optional<Integer> reduce3 = list.stream().map(Person::getAge).reduce((x, y) -> x * y);
        System.out.println("reduce3 :{} " + reduce3.get());

        System.out.println("======== reduce max ========");
        Optional<Person> reduce4 = list.stream().reduce((x, y) -> x.getAge() > y.getAge() ? x : y);
        System.out.println("reduce4 :{} " + reduce4.get());
    }
6. 收集-分组(collect-groupBy)

将一个 list 进行分组转换成多个 Map, 可以进行单级分组和多级分组

   /**
     * 收集-分组 collect-groupBy
     *  将一个 list 进行分组转换成多个 Map, 可以进行单级分组和多级分组
     *  入参是 Function 接口
     */
    public void groupBy() {
        List<Person> list = InitList.initList();
        System.out.println("========== groupBy =============");
        System.out.println("=========== 根据单个属性分组 ============");
        Map<String, List<Person>> collect = list.stream().collect(Collectors.groupingBy(Person::getName));
        System.out.println("groupBy :{name} " + collect.toString());
        List<String> nameLength = list.stream().collect(Collectors.groupingBy(Person::getName)).keySet().stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
        System.out.println("max :{name.length} " + nameLength);

        System.out.println("=========== 根据多个属性拼接分组 ============");
        Map<String, List<Person>> collect1 = list.stream().collect(Collectors.groupingBy(x -> x.getName() + "-" + x.getAge()));
        System.out.println("groupBy :{name-age} " + collect1.toString());

        System.out.println("=========== 根据多条件分组 ============");
        Map<String, List<Person>> collect2 = list.stream().collect(Collectors.groupingBy(x -> {
                    if (x.getAge() > 30) {
                        return "age>30";
                    } else {
                        return "ageOther";
                    }
                }
        ));
        System.out.println("groupBy :{age>30} " + collect2.toString());

        System.out.println("=========== 按子组收集数据[求总数] ============");
        // 分别求男女性别的人数
        Map<String, Long> collect3 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.counting()));
        System.out.println("groupBy :{counting} " + collect3.toString());

        System.out.println("=========== 按子组收集数据[求和] ============");
        // 分别求男性的年龄和以及女性的年龄和
        Map<String, Integer> collect4 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.summingInt(Person::getAge)));
        System.out.println("groupBy :{summing} " + collect4.toString());

        System.out.println("=========== 按子组收集数据[平均值] ============");
        // 分别求男性的平均年龄和女性的平均年龄
        Map<String, Double> collect5 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.averagingInt(Person::getAge)));
        System.out.println("groupBy :{averaging} " + collect5.toString());

        System.out.println("=========== 按子组收集数据[求和/总数/平均值/极值等] ============");
        // Collectors.summarizingDouble();Collectors.summarizingLong(); 同理,只是数据类型不一样
        // 分别求男女性别的一些数值数据
        Map<String, IntSummaryStatistics> collect6 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.summarizingInt(Person::getAge)));
        System.out.println("groupBy :{summarizing} " + collect6.toString());

        System.out.println("========== 按子组收集数据[根据性别分组,每组只保留年龄最大的] =============");
        // 根据性别分组,每组只保留年龄最大的, 如果有年龄相同的默认保存第一个
        Map<String, Person> collect7 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Person::getAge)), Optional::get)));
        System.out.println("groupBy :{} " + collect7.toString());

        System.out.println("========== 联合其他收集器[根据性别分组,每组根据姓名分组,只保留姓名] ===========");
        Map<String, Set<String>> collect8 = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.mapping(Person::getName, Collectors.toSet())));
        System.out.println("groupBy :{} " + collect8.toString());
    }
7. 收集-分区(collect-partitioningBy)

将流按照一定条件转化为两个 Map (入参是 Predicate 接口, 只能根据 true 和 false 分为两组)

    /**
     *  collect-partitioningBy 收集-分区
     *    将流按照一定条件转化为两个 Map (入参是 Predicate 接口, 只能根据 true 和 false 分为两组)
     */
    public void partitioningBy() {
        List<Person> list = InitList.initList();
        System.out.println("========== partitioningBy =============");
        Map<Boolean, List<Person>> collect = list.stream().collect(Collectors.partitioningBy(x -> x.getAge() > 40));
        System.out.println("partitioningBy :{} " + collect.toString());
    }
8. 收集-归集(toList/toSet/toMap)

因为流不存储数据,那么在流中的数据处理完成后,需要将流中的数据重新归集到新的集合里。 toListtoSettoMap比较常用,另外还有toCollectiontoConcurrentMap等复杂一些的用法。

    /**
     *  收集-归集(toList/toSet/toMap)
     *   因为流不存储数据,那么在流中的数据处理完成后,需要将流中的数据重新归集到新的集合里
     */
    public void otherCollections() {
        List<Person> list = InitList.initList();
        System.out.println("========== 转换为其他的集合形式 =============");
        System.out.println("========== toList(年龄大于 40 的人) =============");
        List<Person> collect = list.stream().filter(x -> x.getAge() > 40).collect(Collectors.toList());
        System.out.println("toList(年龄大于 40 的人) :{} " + collect.toString());

        System.out.println("========== toSet(取出所有人的性别) =============");
        Set<String> collect1 = list.stream().map(Person::getSex).collect(Collectors.toSet());
        System.out.println("toSet(取出所有人的性别) :{} " + collect1.toString());

        System.out.println("========== toMap(年龄大于 30 的按照姓名分组) =============");
        Map<String, Person> collect2 = list.stream().filter(x -> x.getAge() > 30).collect(Collectors.toMap(Person::getName, x -> x));
        System.out.println("toMap(年龄大于 30 的按照姓名分组) :{} " + collect2.toString());
    }
9. 收集-统计(collect-count/averaging/maxBy/summing/summarizing)

Collectors提供了一系列用于数据统计的静态方法:

  • 计数:count
  • 平均值:averagingInt、averagingLong、averagingDouble
  • 最值:maxBy、minBy
  • 求和:summingInt、summingLong、summingDouble
  • 统计以上所有:summarizingInt、summarizingLong、summarizingDouble
    /**
     *  收集-统计(count/averaging/maxBy/summing/summarizing)
     *  Collectors提供了一系列用于数据统计的静态方法:
     *      计数:count
     *      平均值:averagingInt、averagingLong、averagingDouble
     *      最值:maxBy、minBy
     *      求和:summingInt、summingLong、summingDouble
     *      统计以上所有:summarizingInt、summarizingLong、summarizingDouble
     */
    public void statistical() {
        List<Person> list = InitList.initList();
        System.out.println("========== Collectors 提供的用于数据统计的静态方法 =============");
        System.out.println("========== 求总数[年龄大于 40 的人数] ==========");
        Long collect = list.stream().filter(x -> x.getAge() > 40).collect(Collectors.counting());
        System.out.println("求总数[年龄大于 40 的人数] :{} " + collect.toString());

        System.out.println("========== 求平均数[年龄大于 30 的人的平均工资] ==========");
        // averagingInt、averagingLong 同理
        Double collect1 = list.stream().filter(x -> x.getAge() > 30).collect(Collectors.averagingDouble(Person::getSalary));
        System.out.println("求平均数[年龄大于 30 的人的平均工资] :{} " + collect1.toString());

        System.out.println("========== 求最值[求最高工资] ==========");
        // minBy 同理
        Optional<Integer> collect2 = list.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
        System.out.println("求最值[求最高工资] :{} " + collect2.get());

        System.out.println("========== 求和[求年龄和] ==========");
        // summingLong、summingDouble 同理
        Integer collect3 = list.stream().collect(Collectors.summingInt(Person::getAge));
        System.out.println("求和[求年龄和] :{} " + collect3.toString());

        System.out.println("========== 求以上所有信息[总数/平均/最值/和] ==========");
        DoubleSummaryStatistics collect4 = list.stream().collect(Collectors.summarizingDouble(Person::getSalary));
        System.out.println("求工资的总数/平均/最值/和] :{} " + collect4.toString());
    }
10. 收集-结合(collect-joining)

joining 可以将 Stream 中的元素用特定的连接符连接成一个字符串,没有指定连接符则直接连接。

    /**
     *  接合(joining)
     *   joining 可以将 Stream 中的元素用特定的连接符连接成一个字符串,没有指定连接符则直接连接。
     */
    public void joining() {
        List<Person> list = InitList.initList();
        System.out.println("======== joining ===========");
        System.out.println("======== 将所有的人的姓名按照,组成一个新的字符串");
        String collect = list.stream().map(Person::getName).collect(Collectors.joining(","));
        System.out.println("result :{} " + collect.toString());
    }
11. 收集-规约(collect-reduce)

Collectors 类提供的 reducing 方法,相比于 stream 本身的 reduce 方法,增加了对自定义规约的支持。

   /**
     *  集合-规约(collect-reduce)
     *   Collectors 类提供的 reducing 方法,相比于 stream 本身的 reduce 方法,增加了对自定义规约的支持。
     */
    public void collectReduce() {
        List<Person> list = InitList.initList();
        System.out.println("======== collect-reduce[计算虚岁年龄和] ===========");
        // 从 0 开始计算虚岁年龄和, 循环中每个年龄元素+1
        Integer collect = list.stream().collect(Collectors.reducing(0, Person::getAge, (x, y) -> x + y + 1));
        System.out.println("result :{} " + collect.toString());
    }
11. 排序(sorted)

Sorted 是中间操作,有两种排序:

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):Comparator排序器自定义排序
    /**
     * sorted 排序
     *  sorted 是中间操作,有两种排序:
     *      1. sorted():自然排序,流中元素需实现Comparable接口
     *      2. sorted(Comparator com):Comparator排序器自定义排序
     */
    public void sorted() {
        List<Person> list = InitList.initList();
        System.out.println("========== sorted =============");
        System.out.println("=========== 单个条件排序(根据年龄倒序排序) ==============");
        List<Person> list1 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
        System.out.println("sorted :{} " + list1.toString());

        System.out.println("=========== 多条件排序(根据年龄降序并根据工资升序) ================");
        List<Person> list2 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed().thenComparing(Person::getSalary)).collect(Collectors.toList());
        System.out.println("sorted :{} " + list2.toString());

        System.out.println("=========== 多条件排序(根据年龄降序并根据工资降序) ================");
        List<Person> list3 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).sorted(Comparator.comparing(Person::getSalary).reversed()).collect(Collectors.toList());
        System.out.println("sorted :{} " + list3.toString());

        System.out.println("=========== 多条件排序(根据年龄降序并根据工资降序2) ================");
        List<Person> list4 = list.stream().sorted((x, y) -> {
            if (x.getAge() == y.getAge()) {
                // return > 0 升序; return < 0 降序
                return y.getSalary() - x.getSalary();
            } else {
                return y.getAge() - x.getAge();
            }
        }).collect(Collectors.toList());
        System.out.println("sorted :{} " + list4.toString());
    }
12. 提取、组合(concat/distinct/limit/skip)

流也可以进行合并、去重、限制、跳过等操作。

Java8Stream 流的使用_第8张图片

    /**
     *  提取、组合(concat/distinct/limit/skip)
     */
    public void other() {
        List<Person> list = InitList.initList();
        System.out.println("======== concat[合并两个流] =========");
        List<Person> list1 = InitList.initList();
        List<Person> collect = Stream.concat(list.stream(), list1.stream()).collect(Collectors.toList());
        System.out.println("concat :{} " + collect.toString());

        System.out.println("======== distinct[去重] ==========");
        List<Person> collect1 = Stream.concat(list.stream(), list1.stream()).distinct().collect(Collectors.toList());
        System.out.println("distinct :{} " + collect1.toString());

        System.out.println("======== limit[限制从流中获得前n个数据] ==========");
        List<Person> collect2 = list.stream().limit(2).collect(Collectors.toList());
        System.out.println("limit :{} " + collect2.toString());
        System.out.println("======== limit[获取年龄最大的两个人] ==========");
        List<Person> collect3 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).limit(2).collect(Collectors.toList());
        System.out.println("result :{} " + collect3.toString());


        System.out.println("======== skip[跳过前n个数据] ==========");
        List<Person> collect4 = list.stream().skip(1).collect(Collectors.toList());
        System.out.println("skip :{} " + collect4.toString());
        System.out.println("======== skip[跳过工资最低的一个人] ==========");
        List<Person> collect5 = list.stream().sorted(Comparator.comparing(Person::getSalary)).skip(1).collect(Collectors.toList());
        System.out.println("result :{} " + collect5.toString());
    }

四、 项目地址

https://github.com/Liuuzhichao/Personal-Practice/tree/master/Stream-Lambda

你可能感兴趣的:(JavaSE,java,lambda,stream,foreach,collect)