Java8特性 stream流常用方法

Java8特性 stream流常用方法

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
代码地址:GitHub

在 Java 8 中, 集合接口有两个方法来生成流:

stream() − 为集合创建串行流。
parallelStream() − 为集合创建并行流。

创建实体类和集合

实体类


package com.dnydys.stream.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Classname Person
 * @Description TODO
 * @Date 2021/12/22 22:35
 * @Created by hasee
 */
@Data
@Builder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    private String firstName;
    private String lastName;
    private String job;
    private String gender;
    private int salary;
    private int age;
}


给集合添加数据


 static List<Person> list = new ArrayList<Person>() {
        {
            add(new Person("1Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
            add(new Person("2Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
            add(new Person("3Floyd", "Donny", "Java programmer", "male", 3322, 25));
            add(new Person("4Sindy", "Jonie", "Java programmer", "female", 35020, 15));
            add(new Person("5Vere", "Hervey", "Java programmer", "male", 2272, 25));
            add(new Person("6Maude", "Jaimie", "Java programmer", "female", 2057, 87));
            add(new Person("7Shawn", "Randall", "Java programmer", "male", 3120, 99));
            add(new Person("8Jayden", "Corrina", "Java programmer", "female", 345, 25));
            add(new Person("9Palmer", "Dene", "Java programmer", "male", 3375, 14));
            add(new Person("10Addison", "Pam", "Java programmer", "female", 3429, 20));
            add(new Person("10Addison", "Pam", "Java programmer", "female", 3429, 20));
            add(new Person("10Addison", "Pam", "Java programmer", "female", 3429, 20));
            // add(new Person("Addison", "Pam", "Java programmer", null, 3422, 20));
        }
    };

创建流的几种方式


 public static void createStream() {

        // 通过集合创建Stream流------> default Stream<E> stream:返回一个顺序流
        Stream<Person> stream = list.stream();

        // 通过集合创建Stream流------> default Stream<E> parallelStream:返回一个并行流
        Stream<Person> parallelStream = list.parallelStream();

        // 通过数组创建Stream流-------> 调用Arrays类的static <T> Stream<T>  Stream<T[] array> :返回一个流
        Person[] arrPerson = new Person[]{list.get(0), list.get(1)};
        Stream<Person> streamObj = Arrays.stream(arrPerson);

        // 通过of创建Stream
        Stream<Integer> streamOf = Stream.of(1, 2, 3, 4, 5, 6);

        Stream<Person> streamOfs = Stream.of(list.get(0), list.get(1));

        //  通过无限流的方式创建Stream流
        /* 迭代--->*public static<T> Stream<T> iterate(final T seed,final UnaruOperator<T> f)
         * 遍历前10个偶数
         * 无限流,无限反复操作使用,所有一般都会配合limit使用
         */
        Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);  //seed是起始数值,limit代表循环前10次

        // 生成----》public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }

filter()方法


public static void testFilter(){
            //`filter`(Predicate p)–接受Lambda,从流中排除某些元素
            //原生方式  所有的中间操作不会做任何的处理
            Stream<Person> stream1 = list.stream()
                .filter((e) ->{
                        return e.getAge() < 20;
                });
            stream1.forEach(System.out::print);

            //使用lambdas表达式优化
            list.stream().filter(
                e->{
                    return e.getAge() < 20;
                }
            ).forEach(System.out::println);
    }

Limit() 和Skip()


   public static void testLimitAndSkip(){
        //   `limit(n)`–截断流,使其元素不超过给定数量  类似于mysql中的limit,但这里只有最大值
        //  `skip(n)`–跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补

        //通过无限流创建一个无限流,如果不使用Limit方法进行限制阶段,无限流将会形成一个类似于死循环的操作
        //当使用skip()将会跳过前5个数据从第6个参数返回
        Stream.iterate(0,t->t+1)
            .limit(10).skip(5)
            .forEach(System.out::println);  //seed是起始数值,limit代表循环前10次
    }

Distinct()


 /**
     * @className TestServiceImpl
     * @author dnydys
     * @description 测试去重
     * @updateTime 2021/12/22 23:32
     * @return: void
     * @version 1.0
     */
    public static void testDistinct(){
        //distinct–筛选,通过流所生成的元素的 hashCode() 和 equals() 去除重复元素
        //distinct取出集合中对象信息完全重复的对象
        list.stream()
            .distinct()
            .forEach(System.out::println);


    }

distinct对集合中对象的某一属性进行去重



	//distinct()不提供按照属性对对象列表进行去重的直接实现
    //它是基于hashCode()和equals()工作的。
    // 如果想要按照对象的属性,对对象列表进行去重,我们可以通过其它方法来实现
    public static <T> Predicate<T> distinctByKey(Function<? super T,?> keyExtractor){
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) ==null;
    }

    /**
     * @className TestServiceImpl
     * @author dnydys
     * @description distinct对集合中对象的某一属性进行去重
     * @updateTime 2021/12/23 0:00
     * @return: void
     * @version 1.0
     */
    public static void testDistinctAttribute(){
        //distinct对集合中对象的某一属性进行去重
        list.stream()
            .filter(
                distinctByKey(e->e.getAge())
            ).distinct()
            .forEach(System.out::println);
    }

Stored()


/**
     * @className TestServiceImpl
     * @author dnydys
     * @description 排序
     * @updateTime 2021/12/23 0:38
     * @return: void
     * @version 1.0
     */
    public static void testStored(){
        List<Integer> list1 = Arrays.asList(12, 43, 65, 3, 4, 0,01, -98);
//        list1.stream().sorted().forEach(System.out::println);

        //按年龄排序
//        list.stream().sorted((e1,e2)
//                    ->(Integer.compare(e1.getAge(), e2.getAge()))
//                )
//            .forEach(System.out::println);
        //按FirstName排序
        list.stream().sorted((e1,e2)
                    ->(e1.getFirstName().compareTo(e2.getFirstName()))
                )
            .forEach(System.out::println);
    }

匹配与查找


 public static void testMatchAndFind(){
        /**
         * 匹配与查找
         *     allMatch(Predicate p):检查是否匹配所有元素
         *     anyMatch(Predicate p):检查是否至少匹配一个元素
         *     noneMatch(Predicate p):检查是否没有匹配的元素
         *     findFirst():返回第一个元素
         *     findAny():返回当前流中的任意元素
         *     count():返回流中元素的总数
         *     max(Comparator c):返回流中最大值
         *     min(Comparator c):返回流中最小值
         *     forEach(Consumer c):内部迭代
         **/

        //allMatch()相当于制定一个规则,将集合中的对象一一与规则进行对象,判断是否所有的集合对象都符合该规则, true/false
        boolean allMatch = list.stream().allMatch(e -> e.getAge()>18);
        System.out.println("测试Stream流的终止操作----allMatch()--->"+allMatch);

        //anyMatch(Predicate p):检查是否至少匹配一个元素  类似于多选一即可
        boolean anyMatch = list.stream().anyMatch(e -> e.getSalary()>1000);
        System.out.println("检查是否至少匹配一个元素----anyMatch()--->"+anyMatch);

        //noneMatch(Predicate p):检查是否没有匹配的元素 没有返回true,反之false
        boolean noneMatch = list.stream().noneMatch(e -> e.getSalary() > 10000);
        System.out.println("检查是否没有匹配的元素----noneMatch()--->"+noneMatch);

        //findFirst():返回第一个元素
        Person person = list.stream().findFirst().get();
        System.out.println("返回第一个元素----findFirst()--->"+person.toString());

        for (int i = 0; i <100 ; i++) {
            // findAny():返回当前流中的任意元素
            Optional<Person> AnyPerson = list.stream().findAny();
            System.out.println("返回当前流中的任意元素----findAny()--->"+AnyPerson.toString()+"--------->"+i);
        }

        //count():返回流中元素的总数
        long count = list.stream().count();
        System.out.println("返回流中元素的总数----count()--->"+count);

        //max(Comparator c):返回流中最大值   Optional<T> max(Comparator<? super T> comparator);
        Person maxPersonSalary = list.stream().max(Comparator.comparing(Person::getSalary)).get();
        System.out.println("返回流中最大值----max()--->"+maxPersonSalary);

        //min(Comparator c):返回流中最小值
        Person minPersonSalary = list.stream().min(Comparator.comparing(Person::getSalary)).get();
        System.out.println("返回流中最小值----max()--->"+minPersonSalary);
    }


规约


public static void testStatute(){
        /*
         * **规约**
         *     reduce(T identity,BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回T
         *     reduce(BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回Optional
         */

        //reduce(BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回Optional
        Integer integers = list.stream().map(Person::getSalary).reduce((e1, e2) -> e1 + e2).get();//lambda表达式
        Integer integer = list.stream().map(Person::getSalary).reduce(Integer::sum).get();//使用引用
        System.out.println("工资总和-------lambda表达式------>"+integers);
        System.out.println("工资总和-------使用引用------>"+integer);

    }

Collector()


 public static void testCollector(){
        /*
        * **收集**
        *     collect(Collector c):将流转换成其他形式。接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
        *       Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。
        *       Collector需要使用Collectors提供实例。另外, Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下:
                    toList:返回类型List< T>,作用是把流中元素收集到List
                    toSet:返回类型Set< T>,作用是把流中元素收集到Set
                    toCollection:返回类型Collection< T>,作用是把流中元素收集到创建的集合
        */

        //collect(Collector c):将流转换成其他形式。返回一个set
        System.out.println("将流转换成其他形式。返回一个set-------toSet()------>:");
        list.stream().filter(e -> e.getSalary() > 3000).collect(Collectors.toSet()).forEach(System.out::println);

        //collect(Collector c):将流转换成其他形式。返回一个list
        System.out.println("将流转换成其他形式。返回一个list-------toList()------>:");
        list.stream().filter(e -> e.getSalary() > 3000).limit(2).collect(Collectors.toList()).forEach(System.out::println);

        //collect(Collector c):将流转换成其他形式。返回一个map
        System.out.println("将流转换成其他形式。返回一个map-------toMap()------>:");
        list.stream().filter(e -> !e.getFirstName().equals("测试"))
            // 注意:key不能重复  toMap()参数一:key   参数二:value   参数三:对key值进行去重,当有重复的key,map中保留第一条重复数据
            .collect(Collectors.toMap(Person::getAge,person -> person,(key1, key2) -> key1))  //value 为对象 student -> student jdk1.8返回当前对象,也可以为对象的属性
            .forEach((key, value) -> System.out.println("key--"+key+"   value--"+value.toString()));


    }

总结:Java8 中
添加了一个新的接口类 Stream,相当于高级版的Iterator,通过Lambda 表达式对集合进行各种非常便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作(Bulk Data Operation)。Stream不仅可以通过串行的方式实现数据操作,还可以通过并行的方式处理大批量数据,提高数据的处理效率。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值