Stream API——Java8新特性

本文详细介绍了Java8中的Stream API,它为集合处理带来函数式编程风格,允许以声明方式处理数据。Stream API包含创建、转换、聚合等操作,支持并行处理和无限流。通过实例展示了如何进行筛选、映射、排序、聚合等操作,以及中间操作和终结操作的使用。理解并掌握Stream API能有效提升Java开发效率。
摘要由CSDN通过智能技术生成

StreamAPI

Java8API中添加了新的抽象称为流Stream,把真正的函数式编程风格引入到Java中,可以让你以一种声明的方式处理数据,Stream使用一种类似SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象,StreamAPI极大简化了集合框架的处理,这种风格将需要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如:筛选、排序、聚合。

Stream流有一些新特性:

  • Stream流不是一种数据类型,不保存数据,他只是在原数据集上定义了一组操作
  • 这些操作是惰性的,即每当访问到这个流中的一个元素时,才会在此元素上执行这一系列的操作
  • Stream流不保存数据,所以一个Stream流只能使用一次
  • 元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果:
    • 中间操作:返回结果都是Stream,所以中间操作可以叠加
    • 最终操作:返回我们最终需要的数据,只能有一个最终操作

使用Stream流,可以清楚地知道我们要对一个数据集做何操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以更加专注于业务逻辑。默认情况下,从有序集合、生成器、迭代器产生的流或者通过调用Stream.sorted产生的流都是有序流,有序流在并行处理时会在处理完成后恢复原顺序。无限流的存在侧面说明了流是惰性的,即每当用到一个元素时,才会在这个元素上执行这一系列操作。

使用Stream流的基本操作:

  • 创建Stream
  • 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以进行多次转换)
  • 对Stream进行聚合操作,获得想要的结果

流的创建

通过集合创建

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

  • default Stream stream();返回一个顺序流
  • default Stream parallelStream();返回一个并行流
通过数组创建

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

  • public staticStream staram(T[] array);返回一个流
  • public static IntStream stream(int[] array);返回一个整型的数据流
  • public static LongStream stream(long[] array);返回一个长整形的数据流
  • public static DoubleStream stream(double[] array);返回一个浮点型数据流
通过Stream创建

1、可以调用Stream类静态方法of(),通过显示值创建一个流,它可以接收任务数量的参数。

  • public static Stream of(T …values);返回一个顺序流

2、静态方法concat(),将两个流连接起来

  • public static Stream concat(Stream<? extends T> a, Stream<? extends T> b);
创建无限流

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

  • public static Stream iterate(final T seed,final UnaryOperatorf);返回一个无限流
  • public static Stream generate(Supplier s);返回一个无限流

中间操作

返回值方法名说明
Streamfilter(Predicate p)筛选,接收Lambda,从流中排除某些元素
Streamdistinct()筛选,通过流所生成元素的equals()去除重复元素
Streamlimit(long maxSize)截断,使流中元素不超过指定maxSize
Streamskip(long n)切片,跳过元素,返回一个扔掉了n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
Streampeek(Consumer action)消费,接收Lambda,对流中每一个数据执行Lambda体操作
Streamsorted()排序,产生一个新流,其中按自然顺序排序
Streamsorted(Comparator com)排序,产生一个新流,其中按给定比较器顺序排序
Streammap(Function f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素
StreamflatMap(Function f)映射,接收一个函数作为参数,将流中的每一个值都替换为另一个流,然后把所有流连接成一个流
DoubleStreammapToDouble(ToDoubleFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的DoubleStream
IntStreammapToInt(ToIntFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的IntStream
LongStreammapToLong(ToLongFunction f)映射,接收一个函数作为参数,该函数会被应用到每一个元素上,产生一个新的LongStream
中间操作:筛选和切片
        ArrayList<Employee> list = new ArrayList<>();
        list.add(new Employee(1001,"张三",3000));
        list.add(new Employee(1002,"李四",5500));
        list.add(new Employee(1003,"王五",8000));
        list.add(new Employee(1004,"赵六",6000));
        list.add(new Employee(1004,"赵六",6000));
        list.add(new Employee(1004,"赵六",6000));

        list.stream()
                .filter((x)->x.getSalary()>5000)//过滤掉工资小于5000的元素
                .limit(4)//只留下前四个元素
                .skip(1)//去掉第一个元素
                .distinct()//去掉重复元素,需要自定义类Employee重写equals和hashCode方法
                .forEach(System.out::println);

中间操作:消费
        List<String> list2 = Arrays.asList("a","bb","c","d");
        list2.stream()
                .peek(System.out::println)//消费这个流中的元素,打印每一个元素
                //注意,这是中间操作,所以需要在下面增加一个终止操作,上面的中间操作才会执行
                .collect(Collectors.toList());

中间操作:排序
        List<String> list1 = Arrays.asList("dd","b","aaa","cccc");
        list1.stream()
                .sorted()//自然排序,使用String类中的compareTo方法实现排序(Comparable)
                .forEach(System.out::println);
        System.out.println("-----------------------------------------");
        list1.stream()
                .sorted((a,b)-> {
                    if (a.length() > b.length()){
                        return 1;
                    }else {
                        return -1;
                    }
                })//定制排序,按字符串长度排序
                .forEach(System.out::println);

中间操作:映射
        String[] strs = {"java","lambda","stream","map","flatmap"};
        Arrays.stream(strs)
                .map((str)->str.split(""))//将每一个字符串都转换为一个字符串数组流
                .forEach(System.out::println);//打印的字符串数组

        Arrays.stream(strs)
                .map((str)->str.split(""))
                .flatMap(Arrays::stream)//将得到的每一个字符串数组流扁平化,在构成一个总流
                .forEach(System.out::println);//打印总流中的每一个字符

终结操作

终结操作是会从流的流水线生成结果,其结果可以是任何不是流的值,如List、Integer、void也可以。流进行了终止操作后,就不能再次使用。

返回值方法名说明
booleanallMatch(Predicate p)接收一个Predicate函数,当流中每个元素都符合该断言时,才会返回true,否则返回false
booleannoneMatch(Predicate p)接收一个Predicate函数,当流中每一个元素都不符合该断言时才返回true,否则返回false
booleananyMatch(Predicate p)接收一个Predicate函数,当流中有一个元素满足该断言则返回true,否则返回false
OptionalfindFirst()返回流中的第一个元素
OptionalfindAny()返回流中的任意一个元素
longcount()返回流中元素的总个数
Optionalmax(Comparator c)返回流中元素的最大值
Optionalmin(Comparator c)返回流中元素的最小值
voidforEach(Consumer c)遍历操作,对此流的每个元素执行操作
Treduce(T iden,BinaryOperator b)规约操作,使用提供的身份值和 associative累积函数对此流的元素执行reduction,并返回减小的值。
Ureduce(BinaryOperator b)规约操作,使用提供的身份,积累和组合功能,对此流的元素执行reduction
Rcollect(Collector c)收集操作,收集一个Collector实例,将流中元素收集成另一个数据结构
终结操作:查找
        ArrayList<Employee> list = new ArrayList<>();
        list.add(new Employee(1001,"张三",3000));
        list.add(new Employee(1002,"李四",5500));
        list.add(new Employee(1003,"王五",8000));
        list.add(new Employee(1004,"赵六",6000));

        boolean b1 = list.stream()
                .allMatch(e -> e.getSalary()>3000);
        System.out.println("员工工资是否都大于3000:"+b1);

        boolean b2 = list.stream()
                .anyMatch(e -> e.getSalary()>7000);
        System.out.println("员工工资是否有大于7000的:"+b2);

        boolean b3 = list.stream()
                .noneMatch(e -> e.getSalary()>10000);
        System.out.println("员工工资是否都不大于一万:"+b3);


        //因为得到的值有可能为空,所以返回的对象是一个Optional
        Optional<Employee> op = list.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary))
                .findFirst();
        System.out.println("工资最低的员工:"+op.get());

        //随机返回一个工资大于五千的员工信息
        Optional<Employee> op1 = list.parallelStream()
                .filter(e->e.getSalary()>5000)
                .findAny();
        System.out.println("工资大于5000的任意一个员工:"+op1.get());

终结操作:匹配
        long count = list.stream()
                .count();
        System.out.println("员工总数为:"+count);

        //返回流中的最大值
        Optional<Employee> op3 = list.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println("工资最高的员工:"+op3.get());

        //返回流中的最小值
        Optional<Double> op4 = list.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println("最低工资为:"+op4.get());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值