Java 8 新特性 Stream API 介绍与使用

Stream 介绍

Java8中有两大最为重要的改变。

第一个是 Lambda表达式;另外一个则是 Stream API (java.util.stream.*)。

Stream是 Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。

使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。

Java 8 新特性 Stream API 介绍与使用

流(Stream)到底是什么?

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算!”

注意:
① Stream自己不会存储元素。
② Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream 的操作三个步骤

● 创建Stream

一个数据源(如集合、数组),获取一个流

● 中间操作

一个中间操作链,对数据源的数据进行处理,

● 终止操作

一个终止操作,执行中间操作链,并产生结果

Java 8 新特性 Stream API 介绍与使用

创建 Stream

Java8 中的Collection接口被扩展,提供了两个获取流的方法:

● default Streamstream() :返回一个顺序流

● default StreamparallelStream() :返回一个并行流

  //1,可以通过 Collection 系列集合提供的 stream() 或者 parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();

由数组创建流

Java8 中的Arrays 的静态方法stream()可以获取数组流:

● staticStreamstream(T[] array):返回一个流

 //2.通过 Arrays 中的静态方法 stream() 获取数组流
 Employee[] emps = new Employee[10];
 Stream<Employee> stream2 = Arrays.stream(emps);

重载形式,能够处理对应基本类型的数组:

public static IntStream stream(int[] array)

public static LongStream stream(long[] array)

public static DoubleStream stream(double[] array)

由值创建流

可以使用静态方法Stream. of(),通过显示值创建一个流。它可以接收任意数量的参数。

public staticStreamof(T.. . values) :返回一个流

   //3.通过 Stream 类中的静态方法 of()
   Stream<String> stream3 = Stream.of("aa""bb""cc");

由函数创建流:创建无限流

可以使用静态方法Stream.iterate()和Stream. generate(),创建无限流。

● 迭代
public staticStreamiterate(final T seed,finalUnaryOperatorf)

● 生成
public staticStreamgenerate (Suppliers) :

  //4.创建无限流
        //迭代
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        stream4.limit(10).forEach(System.out::println);
        //生成
        Stream.generate(() -> Math.random())
                .limit(5)
                .forEach(System.out::println);

Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

筛选与切片

Java 8 新特性 Stream API 介绍与使用

● filter() 使用

   @Test
    public void test1() {
        //内部迭代:迭代操作由Stream API完成
        //中间操作:不会执行任何操作
        Stream<Employee> stream = employees.stream()
                .filter((e -> {
                    return e.getAge() > 35;
                }));
        //中间操作:一次性执行全部内容,即“惰性求值”
        stream.forEach(System.out::println);

● limit() 使用

   @Test
    public void test3() {
        employees.stream()
                .filter((e) -> e.getSalary() > 5000)
                .limit(2)
                .forEach(System.out::println);
    }

● skip()、distinct() 使用

  @Test
    public void test4() {
        employees.stream()
                .filter((e) -> e.getSalary() > 5000)
                .skip(2)
                .distinct()
                .forEach(System.out::println);
    }

映射

Java 8 新特性 Stream API 介绍与使用

● map()、flatMap() 使用

    @Test
    public void test5() {
        List<String> list = Arrays.asList("aaa""bbb""ccc""ddd""eee");
        list.stream()
                .map((str) -> str.toUpperCase())
                .forEach(System.out::println);
        System.out.println("----------------------");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        System.out.println("----------------------");
//        Stream<Stream<Character>> stream = list.stream()
//                .map(TestStreamAPI2::filterCharacter);
//        stream
//                .forEach((sm) -> {
//                    sm.forEach(System.out::println);
//                });

        System.out.println("----------------------");
        Stream<Character> sm = list.stream()
                .flatMap(TestStreamAPI2::filterCharacter);
        sm.forEach(System.out::println);
    }

排序

Java 8 新特性 Stream API 介绍与使用

● sorted() 使用

 @Test
    public void test6() {
        List<String> list = Arrays.asList("ccc""aaa""bbb""ddd""eee");
        list.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("----------------------");
        employees.stream()
                .sorted((e1, e2) -> {
                    if (e1.getAge().equals(e2.getAge())) {
                        return e1.getName().compareTo(e2.getName());
                    } else {
                        return -e1.getAge().compareTo(e2.getAge());
                    }
                }).forEach(System.out::println);
    }

Stream 的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。

查找与匹配

Java 8 新特性 Stream API 介绍与使用
Java 8 新特性 Stream API 介绍与使用

● allMatch()、anyMatch()、findFirst()…使用

    @Test
    public void test2() {
        long count = employees.stream()
                .count();
        System.out.println(count);

        Optional<Employee1> op1 = employees.stream()
                .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(op1.get());

        Optional<Double> min = employees.stream()
                .map(Employee1::getSalary)
                .min(Double::compare);
        System.out.println(min);
    }

    @Test
    public void test1() {
        boolean b = employees.stream()
                .allMatch((e) -> e.getStatus().equals(Employee1.Status.Busy));
        System.out.println(b);
        System.out.println("------------------");
        boolean b1 = employees.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee1.Status.Busy));
        System.out.println(b1);

        boolean b3 = employees.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee1.Status.Busy));
        System.out.println(b3);
        Optional<Employee1> op = employees.stream()
                .sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(op.get());

        Optional<Employee1> op2 = employees.stream()
                .filter(e -> e.getStatus().equals(Employee1.Status.Free))
                .findAny();
        System.out.println(op2.get());
    }

归约

Java 8 新特性 Stream API 介绍与使用

备注:map 和 reduce 的连接通常称为map-reduce 模式,因 Google 用它 来进行网络搜索而出名。

● map()、reduce() 使用

  @Test
    public void test3() {
        List<Integer> list = Arrays.asList(12345678910);
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        Optional<Double> op = employees.stream()
                .map(Employee1::getSalary)
                .reduce(Double::sum);
        System.out.println(op.get());
    }

收集

Java 8 新特性 Stream API 介绍与使用

Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

Java 8 新特性 Stream API 介绍与使用
Java 8 新特性 Stream API 介绍与使用

● toList()、maxBy()、partitioningBy()… 使用

    @Test
    public void test10() {
        String str = employees.stream()
                .map(Employee1::getName)
                .collect(Collectors.joining());
        System.out.println(str);
    }

    @Test
    public void test9() {
        DoubleSummaryStatistics ds = employees.stream()
                .collect(Collectors.summarizingDouble(Employee1::getSalary));
        System.out.println(ds.getAverage());
        System.out.println(ds.getMax());
        System.out.println(ds.getCount());
    }

    //分区
    @Test
    public void test8() {
        Map<Boolean, List<Employee1>> pb = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
        System.out.println(pb);
    }

    //多级分组
    @Test
    public void test7() {
        Map<Employee1.Status, Map<String, List<Employee1>>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee1::getStatus, Collectors.groupingBy((e) -> {
                    if (e.getAge() <= 35) {
                        return "青年";
                    } else if (e.getAge() <= 50) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));
        Set<Map.Entry<Employee1.Status, Map<String, List<Employee1>>>> entries = map.entrySet();
        for (Map.Entry<Employee1.Status, Map<String, List<Employee1>>> entry : entries) {
            System.out.println(entry.getValue());
        }
    }

    //分组
    @Test
    public void test6() {
        Map<Employee1.Status, List<Employee1>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee1::getStatus));
        Set<Map.Entry<Employee1.Status, List<Employee1>>> entrySet = map.entrySet();
        for (Map.Entry<Employee1.Status, List<Employee1>> statusListEntry : entrySet) {
            System.out.println(statusListEntry.getValue());
        }
    }

    @Test
    public void test5() {
        //总数
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);
        System.out.println("-------------------");
        //平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee1::getSalary));
        System.out.println(avg);
        //总和
        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee1::getSalary));
        System.out.println(sum);
        //最大值
        Optional<Employee1> max = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(max.get());
        //最小值
//        Optional<Employee1> min = employees.stream()
//                .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
//        System.out.println(min.get());
        Optional<Double> min = employees.stream()
                .map(Employee1::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

    @Test
    public void test4() {
        List<String> list = employees.stream()
                .map(Employee1::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("-----------------");
        Set<String> list2 = employees.stream()
                .map(Employee1::getName)
                .collect(Collectors.toSet());
        list2.forEach(System.out::println);

        HashSet<String> hs = employees.stream()
                .map(Employee1::getName)
                .collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);
    }

感谢参与

https://www.bilibili.com/video/BV1ut411g7E9?p=7


原文始发于微信公众号(itmkyuan):Java 8 新特性 Stream API 介绍与使用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/39234.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!