Java8新特性-Stream API实战

Java8新特性之Stream API实战

目录

1、Stream概述

2、Stream的创建

3、Stream的使用

案例使用的员工类,这是后面案例中使用的员工类:

3.1 遍历、匹配(foreach、find、match)

3.2 筛选(filter)

3.3 聚合(max、min、count)

3.4 映射(map、flatMap)

3.5 归约(reduce)。map-reduce操作。

3.6 收集(collect)

3.6.1 归集(toList、toSet、toMap)

3.6.2 统计(count、averaging)

3.6.3 分组与分区 (partitioningBy、groupingBy)

3.6.4 接合(joining)

3.7 排序(sorted)

3.8 提取、组合

4、Java内置4大核心函数式接口

5、参考wiki,感谢


1、Stream概述

Java8 中有两个最重要的升级。第一个是 Lambda 表达式,另一个就是 Steam API 表达式。Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以是查找、过滤、映射数据等各种操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。简而言之,Stream API 提供了一种高效且易于使用的数据处理方式。

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

(1)中间操作:每次中间操作都返回一个新的流,可以有多个中间操作。

(2)终止操作:每个流只能进行一次终止操作,终止操作结束后 流无法再次使用。终止操作会产生一个新的集合或值。

另外,Stream 有以下几个特性:

(1)stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。

(2)stream不会改变数据源,通常情况下会产生一个新的集合或一个值。

(3)stream具有延迟执行特性(即:惰性操作),只有调用终止操作时,一系列的中间操作才会一股脑儿执行。

2、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的静态方法创建流:Stream.of()、Stream.iterate()、Stream.generate()

Stream<Integer> stream00 = Stream.of(1, 2, 3);
stream00.forEach(System.out::println); //1 2 3

Stream<Integer> stream11 = Stream.iterate(0, (x) -> x + 2).limit(4);
stream11.forEach(System.out::println); //0 2 4 6

Stream<Double> stream33 = Stream.generate(Math::random).limit(3);
stream33.forEach(System.out::println);// 0.6796156909271994 0.1914314208854283 0.8116932592396652

stream 和 parallelStream 的简单区分: stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数,两者的处理有不同之处。如果流中的数据量足够大,并行流可以加快处速度。除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:

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

3、Stream的使用

在使用stream之前,先理解一个概念:Optional 。

Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,此时调用get()方法会返回该对象中的值。更详细说明请见:菜鸟教程Java 8 Optional类

案例使用的员工类,这是后面案例中使用的员工类:

public class Person implements Serializable {
    private static final long serialVersionUID = 5675706507473016778L;
    private String name;    // 姓名
    private int salary;     // 薪资
    private int age;        // 年龄
    private String sex;     // 性别
    private String area;    // 地区
    public Person() {
    }
    public Person(String name, int salary, int age, String sex, String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }
}

3.1 遍历、匹配(foreach、find、match)

Stream也是支持类似集合的遍历和匹配元素的,只是Stream中的元素是以Optional类型存在的。Stream的遍历、匹配、查找非常简单。

        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 1, 2);
        //遍历输出符合条件的元素
        list.stream()
                .filter(Objects::nonNull)
                .filter(x -> x > 6)
                .forEach(y -> System.out.print(y + "  "));
        System.out.println();
        System.out.println("===================================");

        //匹配第一个
        Optional<Integer> findFirst = list.stream()
                .filter(Objects::nonNull)
                .filter(x -> x > 6)
                .findFirst();
        System.out.println("匹配第一个值:" + (findFirst.isPresent() ? findFirst.get() : -1));
        System.out.println("===================================");

        //匹配任意一个
        Optional<Integer> findAny = list.stream()
                .filter(Objects::nonNull)
                .filter(x -> x > 6)
                .findAny();
        System.out.println("匹配任意一个值:" + (findAny.isPresent() ? findAny.get() : -1));
        System.out.println("===================================");

        //是否包含符合特定条件的元素
        boolean anyMatch = list.stream()
                .filter(Objects::nonNull)
                .anyMatch(x -> x > 16);
        System.out.println("是否存在大于6的值:" + anyMatch);
        System.out.println("===================================");

3.2 筛选(filter)

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

        //案例一:筛选出Integer集合中大于7的元素,并打印出来
        list.stream()
                .filter(Objects::nonNull)
                .filter(x -> x > 7)
                .forEach(y -> System.out.print(y + "  "));
        System.out.println();
        System.out.println("===================================");

        //案例二: 筛选员工中工资高于8000的人,并形成新的集合。 形成新集合依赖collect(收集),后文有详细介绍。
        List<Person> personList = Arrays.asList(
                new Person("Tom", 8900, 23, "male", "New York"),
                new Person("Jack", 7000, 25, "male", "Washington"),
                new Person("Lily", 7800, 21, "female", "Washington"),
                new Person("Anni", 8200, 24, "female", "New York"),
                new Person("Owen", 9500, 25, "male", "New York"),
                new Person("Alisa", 7900, 26, "female", "New York"),
                null
        );
        List<String> nameList = personList.stream()
                .filter(Objects::nonNull)
                .filter(x -> x.getSalary() > 8000)
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println("高于8000的员工姓名:" + nameList);
        System.out.println("===================================");

3.3 聚合(max、min、count)

maxmincount 这些字眼在mysql中我们常用它们进行数据统计。Java stream API 中也引入了这些概念和用法,极大方便了我们对集合、数组的数据统计工作。

        //案例一:获取String集合中最长的元素。
        List<String> stringList = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
        Optional<String> maxLength = stringList.stream()
                .filter(Objects::nonNull)
                .max(Comparator.comparing(String::length));
        System.out.println("最长的字符串:" + (maxLength.isPresent() ? maxLength.get() + "的长度=" + maxLength.get().length() : -1));

        //案例二:获取Integer集合中的最大值。
        List<Integer> integers = Arrays.asList(7, 6, 9, 4, 11, 6);
        //(1)自然排序
        Optional<Integer> maxInteger = integers.stream()
                .filter(Objects::nonNull)
                .max(Integer::compareTo);
        System.out.println("自然排序的最大值:" + (maxInteger.isPresent() ? maxInteger.get() : -1));

        //(2)自定义排序
        Optional<Integer> maxInteger2 = integers.stream()
                .filter(Objects::nonNull)
                .max((o1, o2) -> o1 > o2 ? 1 : (o1 < o2 ? -1 : 0));
        System.out.println("自定义排序的最大值:" + (maxInteger2.isPresent() ? maxInteger2.get() : -1));

        //案例三:获取员工工资最低的人。
        Optional<Person> maxSalaryPerson = personList.stream()
                .filter(Objects::nonNull)
                .min(Comparator.comparing(Person::getSalary));
        System.out.println("员工工资最低值:" + maxSalaryPerson.get().getSalary());

        //案例四:计算Integer集合中大于6的元素的个数。
        List<Integer> integers2 = Arrays.asList(7, 6, 9, 4, 11, 6);
        long count = integers2.stream()
                .filter(Objects::nonNull)
                .filter(x -> x > 6).count();
        System.out.println("integers2中大于6的元素个数:" + count);
        System.out.println("===================================");

3.4 映射(map、flatMap)

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

(1)map:接收一个函数作为参数,该函数会被应用到每一个元素,并将其映射成一个新的元素。

(2)flatMap:接收一个函数作为参数,将流中的每个元素都转换成另一个流,然后把所有的流连接成一个流。

 //案例一:英文字符串数组的元素全部改为大写。整数数组每个元素+3。
        String[] strArr = {"abcd", "bcdd", "defde", "fTr"};
        List<String> strList = Arrays.stream(strArr)
                .filter(Objects::nonNull)
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println("每个元素转为大写:" + strList);

        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> intListNew = intList.stream()
                .filter(Objects::nonNull)
                .map(x -> x + 3)
                .collect(Collectors.toList());
        System.out.println("每个元素+3后:" + intListNew);

        //案例二:将员工的薪资全部增加1000。
        //方法1:不改变原来员工集合的方式(不改变数据源)
        List<Person> personListNew = personList.stream()
                .filter(Objects::nonNull)
                .map(person -> {
                    Person personNew = new Person(person.getName(), 0, 0, null, null);
                    personNew.setSalary(person.getSalary() + 1000);
                    return personNew;
                }).collect(Collectors.toList());
        System.out.println("一次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
        System.out.println("一次改动后:" + personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());

        //方法2:改变原来员工集合的方式(改变了数据源)
        List<Person> personListNew2 = personList.stream()
                .filter(Objects::nonNull)
                .peek(person -> person.setSalary(person.getSalary() + 1000))
                .collect(Collectors.toList());
        System.out.println("二次改动前:" + personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());
        System.out.println("二次改动后:" + personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());
        System.out.println("===================================");

        List<String> collectTemp = Stream.of("one", "two", "three", "four")
                .filter(Objects::nonNull)
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .collect(Collectors.toList());
        System.out.println("peek: " + collectTemp);
        System.out.println("===================================");

        //案例三:将两个字符数组合并成一个新的字符数组。
        List<String> list1 = Arrays.asList("m-k-l-a", "1-3-5-7");
        List<String> list1New = list1.stream()
                .filter(Objects::nonNull)
                .flatMap(s -> Arrays.stream(s.split("-")))
                .collect(Collectors.toList());
        System.out.println("处理前的集合:" + list1);
        System.out.println("处理后的集合:" + list1New);
        System.out.println("===================================");

3.5 归约(reduce)。map-reduce操作。

归约,也称缩减,是把一个流缩减成一个值,能实现对集合求和、求乘积、求最值等操作。Collectors类提供的reducing方法,相比于stream本身提供的reduce方法,增加了对自定义归约的支持。

 //案例一:求Integer集合的元素之和、乘积、最大值。
        List<Integer> integerList = Arrays.asList(1, 3, 2, 8, 11, 4);
        //求和方式一
        Optional<Integer> sum1 = integerList.stream()
                .filter(Objects::nonNull)
                .reduce((x, y) -> x + y);
        //求和方式二
        Optional<Integer> sum2 = integerList.stream()
                .filter(Objects::nonNull)
                .reduce(Integer::sum);
        //求和方式三
        Integer sum3 = integerList.stream()
                .filter(Objects::nonNull)
                .reduce(0, Integer::sum);
        System.out.printf("list求和:%d,%d,%d%n", sum1.get(), sum2.get(), sum3);
        //求乘积
        Optional<Integer> product = integerList.stream()
                .filter(Objects::nonNull)
                .reduce((x, y) -> x * y);
        System.out.printf("list求积:%d%n", product.get());
        //求最大值方式1
        Integer max1 = integerList.stream()
                .filter(Objects::nonNull)
                .reduce(1, Integer::max);
        //求最大值方式2
        Optional<Integer> max2 = integerList.stream()
                .filter(Objects::nonNull)
                .reduce((x, y) -> x > y ? x : y);
        System.out.println("list求和:" + max1 + ", " + max2);

        //案例二:求所有员工的工资之和和最高工资。
        //求工资之和方式1:
        Optional<Integer> sumSalary = personList.stream().filter(Objects::nonNull).map(Person::getSalary).reduce(Integer::sum);
        //求工资之和方式2:
        Integer sumSalary2 = personList.stream().filter(Objects::nonNull).reduce(0, (sum, p) -> sum += p.getSalary(), (sum11, sum22) -> sum11 + sum22);
        //求工资之和方式3:
        Integer sumSalary3 = personList.stream().filter(Objects::nonNull).reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);
        System.out.println("工资之和:" + sumSalary.get() + "," + sumSalary2 + "," + sumSalary3);

        //求最高工资方式1:
        Optional<Integer> maxSalary = personList.stream().filter(Objects::nonNull).map(Person::getSalary).reduce(Integer::max);
        Optional<Integer> minSalary = personList.stream().filter(Objects::nonNull).map(Person::getSalary).reduce(Integer::min);
        //求最高工资方式2:
        Integer maxSalary2 = personList.stream().filter(Objects::nonNull).reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), Integer::max);
        //求最高工资方式3:
        Integer maxSalary3 = personList.stream().filter(Objects::nonNull).reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), (max11, max22) -> max11 > max22 ? max11 : max22);
        System.out.println("最高工资:" + maxSalary.get() + "," + minSalary.get() + "," + maxSalary2 + "," + maxSalary3);
        System.out.println("===================================");

3.6 收集(collect)

collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值,也可以收集成一个新的集合。

collect主要依赖java.util.stream.Collectors类内置的静态方法。

3.6.1 归集(toList、toSet、toMap)

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

        List<Integer> list3 = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
        List<Integer> listNew = list3.stream()
                .filter(Objects::nonNull)
                .filter(x -> x % 2 == 0)
                .collect(Collectors.toList());
        Set<Integer> listSet = list3.stream()
                .filter(Objects::nonNull)
                .filter(x -> x % 2 == 0)
                .collect(Collectors.toSet());
        HashSet<Integer> listHashSet = list3.stream()
                .filter(Objects::nonNull)
                .filter(x -> x % 2 == 0)
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println("toList: " + listNew + ",toSet: " + listSet + ",listHashSet: " + listHashSet);

        Map<String, Person> personMap = personList.stream()
                .filter(Objects::nonNull)
                .filter(p -> p.getSalary() > 9500)
                .collect(Collectors.toMap(Person::getName, p -> p));
        System.out.println("toMap: " + personMap);
        System.out.println("===================================");

3.6.2 统计(count、averaging)

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

  • 计数:count

  • 平均值:averagingIntaveragingLongaveragingDouble

  • 最值:maxByminBy

  • 求和:summingIntsummingLongsummingDouble

  • 统计以上所有的数值:summarizingIntsummarizingLongsummarizingDouble

        //案例:统计员工人数、平均工资、工资总额、最高工资。
        List<Person> personDtoList = Arrays.asList(
                new Person("Tom8", 8000, 23, "male", "New York"),
                new Person("Jack7", 7000, 25, "male", "Washington"),
                new Person("Lily7", 7500, 21, "female", "Washington"),
                new Person("Anni9", 9000, 22, "female", "New York"),
                new Person("Owen9", 9000, 21, "male", "New York"),
                new Person("Alisa10", 10000, 21, "female", "New York"),
                null
        );
        //求员工总数
        long countPerson = personDtoList.stream()
                .filter(Objects::nonNull)
                .count();
        //求平均工资
        float averagePerson = personDtoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.averagingLong(Person::getSalary)).floatValue();
        //求最高工资
        OptionalLong maxPerson = personDtoList.stream()
                .filter(Objects::nonNull)
                .mapToLong(Person::getSalary).max();
        //求工资之和
        long sumPerson = personDtoList.stream()
                .filter(Objects::nonNull)
                .mapToLong(Person::getSalary).sum();
        //一次性统计上述所有信息
        LongSummaryStatistics collect = personDtoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.summarizingLong(Person::getSalary));
        System.out.println("员工总数:" + countPerson);
        System.out.println("员工平均工资:" + averagePerson);
        System.out.println("员工最高工资:" + maxPerson);
        System.out.println("员工工资总和:" + sumPerson);
        System.out.println("员工工资所有统计:" + collect);
        System.out.println("===================================");

3.6.3 分组与分区 (partitioningBy、groupingBy)

  • 分区:将stream按条件分为两个Map,比如员工按薪资是否高于8000分为两部分。

  • 分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。

        //将员工按薪资是否高于8000分组
        Map<Boolean, List<Person>> booleanPersonListMap = personDtoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.partitioningBy(p -> p.getSalary() > 8000));
        System.out.println("员工按薪资是否大于8000分组情况:" + booleanPersonListMap);
        //将员工按性别分组
        Map<String, List<Person>> sexPersonListMap = personDtoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(Person::getSex));
        System.out.println("员工按性别分组情况:" + sexPersonListMap);
        //将员工先按性别分组,再按地区分组
        Map<String, Map<String, List<Person>>> sexMapAreaPersonListMap = personDtoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        System.out.println("员工按性别、地区:" + sexMapAreaPersonListMap);
员工按薪资是否大于8000分组情况:{false=[Person{name='Tom8', salary=8000, age=23, sex='male', area='New York'}, Person{name='Jack7', salary=7000, age=25, sex='male', area='Washington'}, Person{name='Lily7', salary=7500, age=21, sex='female', area='Washington'}], true=[Person{name='Anni9', salary=9000, age=22, sex='female', area='New York'}, Person{name='Owen9', salary=9000, age=21, sex='male', area='New York'}, Person{name='Alisa10', salary=10000, age=21, sex='female', area='New York'}]}

员工按性别分组情况:{female=[Person{name='Lily7', salary=7500, age=21, sex='female', area='Washington'}, Person{name='Anni9', salary=9000, age=22, sex='female', area='New York'}, Person{name='Alisa10', salary=10000, age=21, sex='female', area='New York'}], male=[Person{name='Tom8', salary=8000, age=23, sex='male', area='New York'}, Person{name='Jack7', salary=7000, age=25, sex='male', area='Washington'}, Person{name='Owen9', salary=9000, age=21, sex='male', area='New York'}]}

员工按性别、地区:{female={New York=[Person{name='Anni9', salary=9000, age=22, sex='female', area='New York'}, Person{name='Alisa10', salary=10000, age=21, sex='female', area='New York'}], Washington=[Person{name='Lily7', salary=7500, age=21, sex='female', area='Washington'}]}, male={New York=[Person{name='Tom8', salary=8000, age=23, sex='male', area='New York'}, Person{name='Owen9', salary=9000, age=21, sex='male', area='New York'}], Washington=[Person{name='Jack7', salary=7000, age=25, sex='male', area='Washington'}]}}

3.6.4 接合(joining)

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

        //将员工的姓名连接成字符串
        String nameStr = personDtoList.stream()
                .filter(Objects::nonNull)
                .map(Person::getName)
                .collect(Collectors.joining());
        //将员工的姓名连接成字符串,用","拼接
        String nameStr2 = personDtoList.stream()
                .filter(Objects::nonNull)
                .map(Person::getName)
                .collect(Collectors.joining(","));
        System.out.println("拼接后的字符串:nameStr=" + nameStr + "。nameStr2=" + nameStr2);
        List<String> strings = Arrays.asList("A", "B", "C");
        String string = strings.stream().collect(Collectors.joining("-"));
        System.out.println("拼接后的字符串:" + string);

        //规约操作
        Integer sumC = personDtoList.stream()
                .filter(Objects::nonNull)
                .map(Person::getSalary)
                .reduce(0, (i, j) -> (i + j - 5000));
        System.out.println("员工扣税薪资总和:" + sumC);
        Optional<Integer> sumC2 = personDtoList.stream()
                .filter(Objects::nonNull)
                .map(Person::getSalary)
                .reduce(Integer::sum);
        System.out.println("员工薪资总和:" + (sumC2.isPresent() ? sumC2.get() : 0));
        System.out.println("===================================");

3.7 排序(sorted)

sorted,中间操作。有两种排序:

  • sorted( ):自然排序,流中元素需实现Comparable接口

  • sorted(Comparator com):Comparator排序器自定义排序

        List<Person> personDtoList2 = Arrays.asList(
                new Person("Tom8", 8000, 23, "male", "New York"),
                new Person("Lily7", 7000, 21, "female", "Washington"),
                new Person("Anni9", 9000, 22, "female", "New York"),
                new Person("Owen9", 9000, 21, "male", "New York"),
                new Person("Alisa10", 10000, 21, "female", "New York"),
                null
        );
        //案例:将员工按工资由高到低(工资一样则按年龄由大到小)排序
        //按工资增序排序
        List<String> salaryList = personDtoList2.stream()
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(Person::getSalary))
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println("按工资自然排序:" + salaryList);
        //按工资倒序排序
        List<String> salaryList2 = personDtoList2.stream()
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(Person::getSalary).reversed())
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println("按工资降序排序:" + salaryList2);
        //先按工资自定义倒排再按年龄自定义倒排(从大到小)
        List<String> salaryList4 = personDtoList2.stream()
                .filter(Objects::nonNull)
                .sorted((p1, p2) -> p1.getSalary() == p2.getSalary() ? p2.getAge() - p1.getAge() : p2.getSalary() - p1.getSalary())
                .map(Person::getName)
                .collect(Collectors.toList());
        System.out.println("先按工资自定义倒排再按年龄自定义倒排:" + salaryList4);
        System.out.println("===================================");

3.8 提取、组合

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

  

       String[] arr1 = {"a", "b", "c", "d"};
        String[] arr2 = {"d", "e", "f", "g"};
        List<String> collect1 = Stream.of(arr1, arr2)
                .filter(Objects::nonNull)
                .flatMap(Arrays::stream)
                .collect(Collectors.toList());
        System.out.println("flatMap合并为一个流,其中的元素就是一个个真实的元素:" + collect1);
        Stream<String> stream1 = Stream.of(arr1);
        Stream<String> stream2 = Stream.of(arr2);
        //concat:合并两个流,去重
        List<String> collect2 = Stream.concat(stream1, stream2)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        System.out.println("流合并,不去重:" + collect2);
        //concat:合并两个流,distinct:去重
        List<String> collect3 = Stream.concat(Stream.of(arr1), Stream.of(arr2))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        System.out.println("流合并,去重:" + collect3);
        //limit:限制从流中获得前n个数据
        List<String> collect4 = Stream.concat(Stream.of(arr1), Stream.of(arr2))
                .filter(Objects::nonNull)
                .distinct()
                .limit(3)
                .collect(Collectors.toList());
        System.out.println("limit:" + collect4);
        //skip:跳过前n个数据
        List<String> collect5 = Stream.concat(Stream.of(arr1), Stream.of(arr2))
                .filter(Objects::nonNull)
                .distinct()
                .sorted()
                .skip(3)
                .collect(Collectors.toList());
        System.out.println("skip:" + collect5);

4、Java内置4大核心函数式接口

参考:https://blog.csdn.net/cmm0401/article/details/109382942

5、参考wiki,感谢

https://blog.csdn.net/mu_wind/article/details/109516995

猜你喜欢

转载自blog.csdn.net/cmm0401/article/details/109655115