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

Stream 介绍

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

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

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

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

流(Stream)到底是什么?

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

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

Stream 的操作三个步骤

● 创建Stream

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

● 中间操作

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

● 终止操作

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

创建 Stream

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

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

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

  //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 staticStream iterate(final T seed,finalUnaryOperator f)

● 生成
public staticStreamgenerate (Supplier s) :

  //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 的中间操作

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

筛选与切片

● 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);
    }

映射

● 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);
    }

排序

● 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 。

查找与匹配

● 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());
    }

归约

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

● map()、reduce() 使用

  @Test
    public void test3() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        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());
    }

收集

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

● 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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值