美文网首页
jdk新特性 --> Stream流

jdk新特性 --> Stream流

作者: 刘小刀tina | 来源:发表于2020-08-29 16:04 被阅读0次

    jdk 并行流 求和

    
      /**
       *  JDk8并姓流
       */
      @Test
      public void test7(){
          Instant start = Instant.now();//开始时间
    
          long sum = LongStream.rangeClosed(0, 100000000L)
                  .parallel() //并行流
                  .reduce(0, Long::sum);
          Instant end = Instant.now();//结束时间
          log.info("耗时为:{}秒,结果为:{}", Duration.between(start,end).toMillis(),sum);//耗时
      }
    
    
    

    java stream 流动 多条件分组和规约

      List<Student> list = Arrays.asList(
                new Student(1, "小明", 20, "男", "枝江市", 89.99d),
                new Student(1, "妹妹", 18, "女", "郑州市", 99.99d),
                new Student(1, "Lily", 18, "女", "肇庆市", 69.99d),
                new Student(1, "yanan", 30, "男", "阳江市", 79.99d),
                new Student(1, "杨阳", 35, "男", "广州市", 59.99d),
                new Student(1, "bob", 29, "男", "大庆市", 69.99d)
        );
    
    
        //求平均值
        @Test
        public void test5() {
    
            DoubleSummaryStatistics collect = list.stream()
                    .sorted((Student o1, Student o2) -> o1.getScore().compareTo(o2.getScore()))
                    .skip(1)
                    .sorted((Student o1, Student o2) -> o2.getScore().compareTo(o1.getScore()))
                    .skip(1)
                    .collect(Collectors.summarizingDouble(Student::getScore));
            log.info("平均分为:{}",collect.getAverage());
    
        }
    
    
        /**
         * 规约
         */
        @Test
        public void test4() {
            
            
            // 规约
            IntSummaryStatistics collect = list.stream()
                    .collect(Collectors.summarizingInt(Student::getAge));
            log.info("打印值为:{}",collect.getAverage());
            log.info("打印值为:{}",collect.getCount());
            log.info("打印值为:{}",collect.getMax());
            log.info("打印值为:{}",collect.getMin());
    
            String collect1 = list.stream()
                    .map(Student::getName)
                    .collect(Collectors.joining(",", "---", "---"));
            log.info("打印{}", collect1);
    
    
            //多条件分组
            Map<String, Map<Object, List<Student>>> collect2 = list.stream()
                    .collect(
                            Collectors.groupingBy(Student::getSex,
                                    Collectors.groupingBy(
                                            e -> {
                                                if (((Student) e).getAge() < 20) {
                                                    return "少年";
                                                } else if (((Student) e).getAge() <= 30) {
                                                    return "青年";
                                                } else {
                                                    return "中年";
                                                }
    
                                            }
    
                                    )
                            )
                    );
    
    
            log.info("打印值为:{}",collect2);
    
        }
    
    
       List<Student> list = Arrays.asList(
                new Student(1, "小明", 20, "男", "枝江市", 89.99d),
                new Student(1, "妹妹", 18, "女", "郑州市", 99.99d),
                new Student(1, "Lily", 18, "女", "肇庆市", 69.99d),
                new Student(1, "yanan", 30, "男", "阳江市", 79.99d),
                new Student(1, "杨阳", 35, "男", "广州市", 59.99d),
                new Student(1, "bob", 29, "男", "大庆市", 69.99d)
        );
    
    
        @Test
        public void test5() {
    
            DoubleSummaryStatistics collect = list.stream()
                    .sorted((Student o1, Student o2) -> o1.getScore().compareTo(o2.getScore()))
                    .skip(1)
                    .sorted((Student o1, Student o2) -> o2.getScore().compareTo(o1.getScore()))
                    .skip(1)
                    .collect(Collectors.summarizingDouble(Student::getScore));
            log.info("平均分为:{}",collect.getAverage());
    
        }
    

    1. 概述

    Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

    特点:
    1 . 不是数据结构,不会保存数据。
    2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)
    3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。

    2. 分类


    无状态:指元素的处理不受之前元素的影响;
    有状态:指该操作只有拿到所有元素之后才能继续下去。
    非短路操作:指必须处理所有元素才能得到最终结果;
    短路操作:指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

    1. Stream流创建的4种方式

    
    /**
     * @program: demo-lambda
     * @description
     *
     *  1. stream关注的是对数据的运算, 与CPU打交道
     *      集合关注的是数据存储,与内存打交道
     *
     *  2 stream自己不会存储元素
     *  stream不会改变缘对象,相反会返回一个持有结果的新的stream
     *  stream 操作是延迟执行的,这意味着他们会等着需要结果的时候才执行
     *
     * @author: tina.liu
     * @create: 2020-08-29 13:58
     **/
    
    @Slf4j
    public class DemoStream {
    
    
        /***
         * 创建工作流的方式1: 通过集合
         *                   default Stream<E> stream(): 返回一个顺序流
         *                   default stream<E> parallelStream(): 返回一个并行流
         *
         * 创建stream方式二 通过数组
         *                  static<T> Stream<T> stream(T[] array):返回一个流
         *
         * 创建stream方式三 通过stream的of()
         *                  public static<T> Stream<T> of(T... values):返回一个流
         *
         * 创建Stream方式四 创建无限流
         *                  迭代
         *                  public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
         *                  生产
         *                  public static<T> Stream<T> generate(Supplier<T> s)
         *
         */
    
        @Test
        public void test1(){
    
    
            List<User> users = User.userList();
    
            //返回一个顺序流
            Stream<User> stream = users.stream();
    
    
            //返回一个并行流
            Stream<User> userStream = users.parallelStream();
    
    
        }
    
        @Test
        public void test2(){
            //创建一个数组
            int[] arr = new int[]{1,2,3,4,5,6};
            //生成流
            IntStream stream = Arrays.stream(arr);
    
            User[] arr2 =  new User[]{new User(1, "tina"),new User(2, "yoyo")};
            Stream<User> stream1 = Arrays.stream(arr2);
    
        }
    
        @Test
        public void test3(){
            Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8);
        }
    
        @Test
        public void test4(){
    
            //迭代
            Stream.iterate(0,t -> t+2).limit(100).forEach(System.out::println);
    
            Stream.generate(Math::random).limit(100).forEach(System.out::println);
    
        }
    
    }
    
    
    

    2. Stream流的中间操作



    public class Demo2{
    
    
        List<User> userList = User.userList();
    
    
        // 去重
        @Test
        public void test1(){
    
            userList.stream()
                    .filter(e-> e.getAge()>=10 )
                    //.skip()
                    //.limit(10)
                    //.distinct()
                    //根据对象指定的字段去重
                    .collect(Collectors.toMap(User::getAccount, Function.identity(),(oldValue,newValue) ->oldValue))
                    .values()
                    .stream()
                    .forEach(System.out::println);
    
            userList.stream()
                    //根据1个条件去重
                    .collect(Collectors.toCollection(() ->new TreeSet<>(Comparator.comparing(User::getAccount))))
                    .stream()
                    .forEach(System.out::println);
    
    
            userList.stream()
                    //根据多个条件去重
                    .collect(Collectors.toCollection(() ->new TreeSet<>(Comparator.comparing(o->o.getAge() +";"+ o.getAccount()))))
                    .stream()
                    .forEach(System.out::println);
    
        }
    
        //过滤
        @Test
        public  void test2(){
            List<String> list = Arrays.asList("aaaaa","bbbbb","ccccc","ddddd","eeeee","fffff","ggggg");
            list.stream()
                .map(str -> str.toUpperCase())
                .forEach(System.out::println);
    
    
            userList.stream()
                    .map(User::getAccount)
                    .filter(account -> account.contains("a"))
                    .forEach(System.out::println);
        }
    
    
    
        //排序
        @Test
        public  void test3(){
            List<String> list = Arrays.asList("aaaaa","bbbbb","ccccc","ddddd","eeeee","fffff","ggggg");
    
            list.stream()
                 .sorted()
                 .forEach(System.out::println);
    
            userList.stream()
                    .sorted((o1, o2) -> {
                        int ageValue = Integer.compare(o1.getAge(),o2.getAge());
                        if(ageValue != 0){
                            return ageValue;
                        }else {
                         return Integer.compare(o1.getId(),o2.getId()) ;
                        }
                    })
                    .forEach(System.out::println);
    
        }
    }
    
    

    3. Stream流的终止操作




    image.png
    
    @Slf4j
    public class Demo2 {
    
    
        List<User> userList = User.userList();
    
        /**
         * 归约
         *  reduce(T identity,BinaryOperator) 可以将流中的元素反复结合起来,得到一个值。比如计算 1~10的和
         *  reduce(BinaryOperator) 可以将流中的元素反复结合起来,得到一个值。如 计算公司所有员工工资的和
         *
         */
        @Test
        public void test11() {
    
            Optional<Integer> reduce = userList.stream()
                    .map(User::getAge)
                    .reduce(Integer::sum);
            log.info(" 返回值{}",reduce);
    
    
            Optional<Double> reduce1 = userList.stream()
                    //根据多个条件去重
                    .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getAccount()+";"+ o.getSex()))))
                    .stream()
                    .map(User::getSalary)
                    .reduce(Double::sum);
            log.info(" 返回值{}",reduce1);
    
        }
    
        /**
         * collect(Collector c) 将流转换为其他形式
         * 
         */
        @Test
        public void test31() {
    
            List<User> collect = userList.stream()
                    .filter(e -> e.getAge() >= 20)
                    .collect(Collectors.toList());
            collect.stream().forEach(System.out::println);
    
    
            Set<User> collect2 = userList.stream()
                    .filter(e -> e.getAge() >= 20)
                    .collect(Collectors.toSet());
            collect2.stream().forEach(System.out::println);
    
    
        }
    
    
    }
    
    
    
    
    package com.tina.demolambda.lambdaDemo2;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.util.*;
    import java.util.function.Supplier;
    import java.util.regex.Pattern;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    /**
     * @program: demo-lambda
     * @description
     * @author: tina.liu
     * @create: 2020-06-01 16:51
     **/
    @Slf4j
    public class Demo2 {
    
    1. 流的常用创建方法:
    
        List<Integer> nums=  new ArrayList<Integer>();//"1",null,"3","4",null,"6"
    
        @Test
        public void test(){
            nums.add(1);
            nums.add(null);
            nums.add(3);
            nums.add(4);
            nums.add(null);
            nums.add(3);
            nums.add(7);
            nums.add(4);
            nums.add(10);
            //利用steam流处理 得到 集合中值不为null的总个数
            long count = nums.stream().filter(num -> num != null).count();
            log.info("集合中值不为null的总个数{}",count);
        }
    
        @Test
        public void test2(){
            //获取stream流的方式
            Stream<Integer> integerStream = Stream.of(1, 2, 3, 5);
            Stream<String> stringStream = Stream.of("taobao");
    
            //利用接口生成一个 stream流对象
            Stream<Double> stream = Stream.generate(new Supplier<Double>() {
                @Override
                public Double get() {
                    return Math.random();
                }
            }); //第一种方式
            Stream.generate(()->Math.random()); //第二种方式
    
            Stream.generate(Math::random); //第三种方式
        }
    
        @Test
        public void test3(){
            //list集合
            List<String> list = new ArrayList<>();
            Stream<String> stream1 = list.stream(); //获取一个顺序流
            Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
    
            //数组
            Integer[] nums = new Integer[10];
            Stream<Integer> stream2 = Arrays.stream(nums);
    
            Stream<Integer> stream3 = Stream.of(1,2,3,4,5,6);
    
            Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2).limit(6);
            stream4.forEach(System.out::println); // 0 2 4 6 8 10
    
            Stream<Double> stream5 = Stream.generate(Math::random).limit(2);
            stream5.forEach(System.out::println);
        }
    
        @Test
        public void  TEST4(){
            // 使用 BufferedReader.lines() 方法,将每行内容转成流
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader("/Users/lvxiaokai/Desktop/刘亚男日报.xlsx"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            Stream<String> lineStream = reader.lines();
            lineStream.forEach(System.out::println);
        }
    
        @Test
        public  void Test5(){
            //使用 Pattern.splitAsStream() 方法,将字符串分隔成流
            Pattern pattern = Pattern.compile(",");
            Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
            stringStream.forEach(System.out::println);
        }
    
    
    2. 流的中间操作
        @Test
        public  void Test6(){
            /** 流的中间操作
             * filter:过滤流中的某些元素
             *         limit(n):获取n个元素
             *         skip(n):跳过n元素,配合limit(n)可实现分页
             *         distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
             */
            Stream<Integer> stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
            Stream<Integer> newStream = stream.filter(s -> s > 5) //6 6 7 9 8 10 12 14 14
                    .distinct() //6 7 9 8 10 12 14
                    .skip(2) //9 8 10 12 14
                    .limit(2); //9 8
            newStream.forEach(System.out::println);
        }
    
        @Test
        public void Test7(){
            /**
             * map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
             * flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
             */
            List<String> list = Arrays.asList("a,b,c", "1,2,3");
    
            //将每个元素转成一个新的且不带逗号的元素
            Stream<String> s1 = list.stream().map(s -> s.replaceAll(",", ""));
            s1.forEach(System.out::println); // abc  123
    
    
            Stream<String> s3 = list.stream().flatMap(s -> {
                //将每个元素转换成一个stream
                String[] split = s.split(",");
                Stream<String> s2 = Arrays.stream(split);
                return s2;
            });
            s3.forEach(System.out::println); // a b c 1 2 3
        }
    
    
      @Test
        public void test13(){
            List<String> list = new ArrayList<>();
            list.add("aaa bbb ccc");
            list.add("ddd eee fff");
            list.add("ggg hhh iii");
            list = list.stream().map(s -> s.split(" ")).flatMap(Arrays::stream).collect(toList());
            log.info("list的值为{}",list);
    
        }
    
    
        @Test
        public void test8(){
    
            //1.遍历List集合并输出
            List<String> list = Arrays.asList("aa", "ff", "dd");
            list.stream().sorted().forEach(System.out::println);
    
            //2.自定义排序,先按照姓名升序 姓名相同则按照年龄升序
            Student s1 = new Student("aaa",10);
            Student s2 = new Student("bbb",11);
            Student s3 = new Student("ccc",13);
            Student s4 = new Student("aaa",20);
            List<Student> studentList = Arrays.asList(s1, s2, s3, s4);
            studentList.stream().sorted(
                    (o1,o2)  ->{
                        if (o1.getName().equals(o2.getName())){
                            return o1.getAge().compareTo(o2.getAge());
                        }else {
                            return o1.getName().compareTo(o2.getName());
                        }
                    }
            ).forEach(System.out::println);
        }
    
    
    
        @Test
        public void test9(){
            // peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。
            Student s1 = new Student("aa",12);
            Student s2 = new Student("bb",18);
            List<Student> studentList = Arrays.asList(s1, s2);
            studentList.stream()
                    .peek(o ->{
                        o.setAge(100);
                    })
                    .forEach(System.out::println);
    
        }
    
    
    3. 流的终止操作
        @Test
        public void test10(){
            /**
             *流的终止操作
             *
             * 3.1 匹配、聚合操作
             *         allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
             *         noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
             *         anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
             *         findFirst:返回流中第一个元素
             *         findAny:返回流中的任意元素
             *         count:返回流中元素的总个数
             *         max:返回流中元素最大值
             *         min:返回流中元素最小值
             */
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
            //1.
            boolean flag1 = list.stream().allMatch(e -> e > 10); //false
            log.info("allMatch返回的值为:{}",flag1);
    
            //2.
            boolean flag2 = list.stream().noneMatch(e -> e < 5); //false
            log.info("noneMatch返回的值为:{}",flag2);
    
            //3.
            Integer integer = list.stream().findFirst().get();
            log.info("流中的第一元素为{}",integer);
    
            //4.
            Integer integer1 = list.stream().findAny().get();
            log.info("流中的任意一个元素为{}",integer1);
    
            //5.
            long count = list.stream().count();
            log.info("流中元素的个数为{}",count);
    
            //6.
            Integer max = list.stream().max(Integer::compareTo).get();
            Integer min = list.stream().min(Integer::compareTo).get();
            log.info("流的元素中,最大值为{},最小值为{}",max,min);
    
        }
    
        @Test
        public void  test11(){
            /**
             * 规约操作
             */
    
            //经过测试,当元素个数小于24时,并行时线程数等于元素个数,当大于等于24时,并行时线程数为16
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
            //1.
            Integer num = list.stream().reduce((x1, x2) -> x1 + x2).get();
            log.info("num的值为{}",num);
            //2.
            Integer reduce = list.stream().reduce(10, (x1, x2) -> x1 + x2);
            log.info("reduce的值为{}",reduce);
            //3.
            Integer cacul = list.stream().reduce(0,
                    (x1, x2) -> {
                        return x1 - x2;
                    },
                    (x1, x2) -> {
                        return x1 * x2;
                    }
            );
            log.info("cacul的值为{}",cacul);
            //4.
            Integer cacul2 = list.parallelStream().reduce(0,
                    (x1, x2) -> {
                        return x1 - x2;
                    },
                    (x1, x2) -> {
                        return x1 * x2;
                    });
            log.info("cacul2的值为{}",cacul2);
    
    计算年龄总和:
    int sum = list.stream().map(Person::getAge).reduce(0, (a, b) -> a + b);
    与之相同:
    int sum = list.stream().map(Person::getAge).reduce(0, Integer::sum);
        }
    
    
    计算年龄总乘积:
    int sum = list.stream().map(Person::getAge).reduce(1, (a, b) -> a * b);
    Optional<Integer> sum = 
    
        @Test
        public void test12(){
            Student s1 = new Student("aaa",10);
            Student s2 = new Student("bbb",11);
            Student s3 = new Student("ccc",13);
            Student s4 = new Student("ee",20);
            List<Student> studentList = Arrays.asList(s1, s2, s3, s4);
    
            //1 将Student对象的某个属性转换为list
            List<Integer> ageList = studentList.stream().map(Student::getAge).collect(Collectors.toList());
            //log.info("将Student对象的某个属性转换为list,为{}",ageList);
            //2 将Student对象的某个属性转换为set
            Set<Integer> ageSet = studentList.stream().map(Student::getAge).collect(Collectors.toSet());
            //log.info("将Student对象的某个属性转换为set,{}",ageSet);
            //3. 将Student对象的某个属性转换为map
            Map<String, Integer> studentMap = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
            //log.info("将Student对象的某个属性转换为map,{}",studentMap);
            //4.分组
            Map<Integer, List<Student>> ageMap = studentList.stream().collect(Collectors.groupingBy(Student::getAge));
            //log.info("分组{}",ageMap);
            //5 分区  分成两部分,一部分大于10岁,一部分小于等于10岁
            Map<Boolean, List<Student>> collect = studentList.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
            log.info("分区{}",collect);
            //6 规约
            Integer integer = studentList.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get();
            log.info("规约之后的值为{}",integer);
    
        }
    
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Student{
        private String name;
        private Integer age;
    }
    

    相关文章

      网友评论

          本文标题:jdk新特性 --> Stream流

          本文链接:https://www.haomeiwen.com/subject/fbxjsktx.html