zoukankan      html  css  js  c++  java
  • java流stream的一些简单用法

    @Data
    @AllArgsConstructor
    public class Student {
        private String name;
        private Integer score;
        private Integer age;
    }
    
    public class StreamTest {
    
        
        /**
         * flatMap 接收一个流的来源(比如list), 返回一个流
         * 将多个流,打平, 使其成为一个流
         */
        @Test
        public void Test3() {
            Stream<List<Integer>> stream = Stream.of(Arrays.asList(1), Arrays.asList(2,3), Arrays.asList(4,5,6));
            stream.flatMap(list -> list.stream()).map(x->x*x).forEach(System.out::println);
    
            List<String> list2 = Arrays.asList("hello world", "world hello", "hello world hello", "hello welcome");
            list2.stream().map(item -> item.split(" ")) // 拆成单词
                    .flatMap(Arrays::stream) // 打平, 将每个数组处理成流
                    .distinct() // 去重, 根据equals方法
                    .forEach(System.out::println);
        }
    
        /**
         * flatMap的更深入使用, 核心就在于将多个stream打平成一个stream, 其入参就是stream类型的
         * 利用两个list交叉打招呼, 相当于两个list的求笛卡尔积
         */
        @Test
        public void Test31() {
            List<String> list1 = Arrays.asList("Hi", "Hello", "你好");
            List<String> list2 = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    
            List<String> result = list1.stream()
                    .flatMap(item -> list2.stream().map(item2 -> item + " " + item2))
                    .collect(Collectors.toList());
            result.forEach(System.out::println);
        }
    
        @Test
        public void Test4() {
            // generate方法, 传入一个生产者
            Stream<String> stream = Stream.generate(UUID.randomUUID()::toString);
            // findFirst 返回一个 optional
            stream.findFirst().ifPresent(System.out::println);
        }
    
        /**
         * Stream.iterate()
         * 接收一个种子, 和一个行为
         * 这个行为会以种子为初始值, 不断的累加执行,返回一个无限的串行流
         * 所以在使用这个方法时, 一般会加一个limit()方法, 来限制长度
         */
        @Test
        public void Test5() {
            Stream.iterate(1, item -> item + 2)
                    .limit(6)
                    .forEach(System.out::println);
            System.out.println("-------------------------");
            IntSummaryStatistics collect = Stream.iterate(1, item -> item + 2)
                    .limit(6)
                    .filter(x -> x > 2) // 过滤
                    .map(x -> x * 2) // 转换
                    .skip(2)  // 忽略前两个元素
                    .limit(2) // 只取前两个元素
                    .collect(Collectors.summarizingInt(x -> x));// 求出结果集,集中包含很多操作
            System.out.println(collect.getSum());
        }
    
        /**
         * 串行流与并行流的排序时间对比
         * 串行流 : 9619
         */
        @Test
        public void Test6() {
            List<String> list = new ArrayList<>(5000000);
            for (int i = 0; i < 5000000; ++i) {
                list.add(UUID.randomUUID().toString());
            }
            System.out.println("开始排序");
            long startTime = System.nanoTime();
            list.stream().sorted().findFirst();
            long endTime = System.nanoTime();
            long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
            System.out.println("排序耗时: " +millis);
        }
    
        /**
         * 串行流与并行流的排序时间对比
         * 并行流: 2235
         */
        @Test
        public void Test7() {
            List<String> list = new ArrayList<>(5000000);
            for (int i = 0; i < 5000000; ++i) {
                list.add(UUID.randomUUID().toString());
            }
            System.out.println("开始排序");
            long startTime = System.nanoTime();
            list.parallelStream().sorted().findFirst();
            long endTime = System.nanoTime();
            long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
            System.out.println("排序耗时: " +millis);
        }
    
        /**
         * stream还提供了和sql一样的分组功能, 分组结果一般是返回map
         * 根据谁分组, 谁就是key
         */
        @Test
        public void Test8() {
            Student s1 = new Student("zhangsan", 100, 20);
            Student s2 = new Student("lisi", 90, 20);
            Student s3 = new Student("wangwu", 90, 30);
            Student s4 = new Student("zhangsan", 80, 40);
    
            List<Student> students = Arrays.asList(s1, s2, s3, s4);
            // 按名字对学生分组
            /* 传统做法: 
            结果: Map<String, List<Student>>
            * 1. 循环列表
            * 2. 取出学生名字
            * 3. 检查map中是否存在该名字, 不存在直接添加到该map,
            * 存在则将map中的List对象取出来,然后添加到list中
            * 4. 返回map对象
            * */
            // stream做法:
            Map<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getName));
            map.forEach((key, value) -> System.out.println("key: " + key + "
    value: " + value));
            System.out.println("-----------------------------------------");
    
            // 根据分数来分组
            Map<Integer, List<Student>> map2 = students.stream().collect(Collectors.groupingBy(Student::getScore));
            map2.forEach((key, value) -> System.out.println("key: " + key + "
    value: " + value));
            System.out.println("-----------------------------------------");
    
            // 分组后,返回数量
            Map<String, Long> m3 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
            m3.forEach((key, value) -> System.out.println("key: " + key + "
    value: " + value));
            System.out.println("-----------------------------------------");
    
            // 分组后,返回分数平均值
            Map<String, Double> m4 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.averagingDouble(Student::getScore)));
            m4.forEach((key, value) -> System.out.println("key: " + key + "
    value: " + value));
    
        }
    
        /**
         * stream分区, 分区是分组的一种特例, 只把数据分为两组
         * 返回一个map, key是bool类型, 表明是否符合分区条件
         */
        @Test
        public void Test9() {
            Student s1 = new Student("zhangsan", 100, 20);
            Student s2 = new Student("lisi", 90, 20);
            Student s3 = new Student("wangwu", 90, 30);
            Student s4 = new Student("zhangsan", 80, 40);
    
            List<Student> students = Arrays.asList(s1, s2, s3, s4);
            Map<Boolean, List<Student>> map = students.stream()
                    .collect(Collectors.partitioningBy(student -> student.getScore() >= 90));
            map.forEach((key, value) -> System.out.println("key: " + key + "
    value: " + value));
    
        }
    
        @Test
        public void Test() {
            Student s1 = new Student("zhangsan", 80);
            Student s2 = new Student("lisi", 90);
            Student s3 = new Student("wangwu", 100);
            Student s4 = new Student("zhaoliu", 90);
            Student s5 = new Student("zhangsan", 70);
            Student s6 = new Student("wangwu", 50);
            List<Student> students = Arrays.asList(s1, s2, s3, s4, s5, s6);
    
            // 在分组的基础上,再次分组, 先根据分数分组, 再根据名字分组
            Map<Integer, Map<String, List<Student>>> map = students.stream().collect(Collectors.groupingBy(Student::getScore, Collectors.groupingBy(Student::getName)));
            System.out.println(map);
            System.out.println("-------------------------");
            // 两次分区
            Map<Boolean, Map<Boolean, List<Student>>> map2 = students.stream().collect(Collectors.partitioningBy(s -> s.getScore() > 80, Collectors.partitioningBy(s -> s.getScore() > 90)));
            System.out.println(map2);
            System.out.println("-------------------------");
            // 先分区, 再求出分区中学生数量
            Map<Boolean, Long> map3 = students.stream().collect(Collectors.partitioningBy(s -> s.getScore() > 80, Collectors.counting()));
            System.out.println(map3);
            System.out.println("-----------------------------");
            // 先根据名字进行分组, 再收集组中分数最小的学生
            Map<String, Optional<Student>> map4 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.minBy(Comparator.comparingInt(Student::getScore))));
            System.out.println(map4);
            System.out.println("---------------------------------");
            // 对map4 的优化,先根据名字进行分组, 再收集组中分数最小的学生, 由于先分组了,
            // 所以后面比较的时候一定有元素,可以直接get到值,少一次Optional操作
            Map<String, Student> map5 = students.stream()
                    .collect(Collectors.groupingBy(Student::getName,
                            Collectors.collectingAndThen(
                                    Collectors.minBy(Comparator.comparingInt(Student::getScore)),
                                    Optional::get)
                            )
                    );
            System.out.println(map5);
            System.out.println("---------------------------------");
        } 
    }
    
  • 相关阅读:
    16. 3Sum Closest
    17. Letter Combinations of a Phone Number
    20. Valid Parentheses
    77. Combinations
    80. Remove Duplicates from Sorted Array II
    82. Remove Duplicates from Sorted List II
    88. Merge Sorted Array
    257. Binary Tree Paths
    225. Implement Stack using Queues
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/Lothlorien/p/12142626.html
Copyright © 2011-2022 走看看