java8Stream流的学习

StreamApi

流(Stream)是什么?

是数据渠道,用于操作数据源(集合 ,数组等)所生成的元素序列

集合讲的是数据,流讲的是计算

注意:

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

Stream 操作的三歌步骤:

  • 创建 Stream

    • 一个数据源(集合、数组)获取流
  • 中间操作

    • 对数据流进行处理
  • 终止操作

    • 产生结果
1、创建Stream流的方式:
  • 可用通过collection系列的集合提供的stream() 或parallelStream() 并行流
  • 通过Arrays中的静态方法stream()
  • 通过Stream中的静态方法of()
  • 创建无限流
    @Test
    //创建流的方式
    public void test1() {

        //1、可用通过collection系列的集合提供的stream() 或parallelStream() 并行流
        ArrayList<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //2、通过Arrays中的静态方法stream()
        int[] ints = new int[10];
        IntStream stream1 = Arrays.stream(ints);

        //3、通过Stream中的静态方法of()
        Stream<String> stream2 = Stream.of("aa", "bb", "c");

        //4、创建无限流
        Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 1);
    }
2、中间操作

中间操作不会执行任何的处理,只有遇到终止操作时,流才会一次性的全部处理。(惰性求值)

  • 筛选与切片

    • filter 接收lambda,从流中排除某些元素
    • limit 截断流,使其元素不超过给定的数值
    • skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补
    • distinct 通过流中元素的hashCode() 和equals() 去除重复元素
        List<Employee> employees = Arrays.asList(
    
                new Employee("张三", 18, 3000),
                new Employee("李四", 18, 3000),
                new Employee("张三", 45, 8700),
                new Employee("王五", 26, 4500),
                new Employee("麻子", 30, 2700),
                new Employee("田七", 15, 200)
    
        );
    
        @Test
        public void test2(){
            employees.stream()
                    //过滤拿到员工年龄超过20岁的
                    .filter((e) -> e.getAge() > 20)  
                    //Employee{name='张三', age=45, salary=8700.0}
                    //Employee{name='王五', age=26, salary=4500.0}
                    //Employee{name='麻子', age=30, salary=2700.0}
                
                	//取出前两个元素
                    .limit(2)
                    //Employee{name='张三', age=45, salary=8700.0}
                    //Employee{name='王五', age=26, salary=4500.0}
                
                	//跳过前一个元素
                    .skip(1)
                    //Employee{name='王五', age=26, salary=4500.0}
                
                 	 //去除重复(这里没有重复的)
                    .distinct()
                    
                    //终止操作
                    .forEach(System.out::println);
        }
    
  • 映射

    • map 接收lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的流。
    • flatMap 接收一个函数作为参数,将流中的每个值换成另一个流,然后把所有的流连接成一个流。
        @Test
        public void test3(){
            List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
    
            list.stream()
                    //把字符转大写
                    .map((s)-> s.toUpperCase(Locale.ROOT))
                    //AAA BBB  CCC DDD
                    .forEach(System.out::println);
    
            //获取数组中每个元素的字符
            list.stream()
                    .map(StreamApiTest::filterString)
                    .forEach(sm -> sm.forEach(System.out::println));
            // a a a b b b c c c d d d 
            
            Stream<Stream<Character>> streamStream = list.stream()
                    .map(StreamApiTest::filterString);
            streamStream.forEach((sm) -> sm.forEach(System.out::println));
            // a a a b b b c c c d d d 
            
            //用这个方法相当于上面的处理方法
            list.stream()
                    .flatMap(StreamApiTest::filterString)
                    .forEach(System.out::println);        
            // a a a b b b c c c d d d 
    
    
        }
        //将字符串转化成字符流
        public static Stream<Character> filterString(String str){
            ArrayList<Character> list = new ArrayList<>();
    
            for (char c : str.toCharArray()) {
                list.add(c);
            }
            return list.stream();
        }
    
  • 排序

    • sorted() 自然排序( 按照comparable)比如String 中的comparaTo (实现了comparable接口的类)
    • sorted( Comparator) 定制排序 (自己写的conparator排序)
        @Test
        public void test4() {
            List<String> list = Arrays.asList("aaa", "ccc", "bbb", "ddd");
    
            list.stream()
                    //按照String中的实现了comparable的排序规则
                    .sorted()
                    .forEach(System.out::println);
    
                    // aaa bbb ccc ddd
    
    
            employees.stream()
                    //按照自己写的排序规则来排序
                    .sorted((e1,e2)-> Integer.compare(e1.getAge(),e2.getAge()))
                    .forEach(System.out::println);
            
                    //Employee{name='田七', age=15, salary=200.0}
                    //Employee{name='张三', age=18, salary=3000.0}
                    //Employee{name='李四', age=18, salary=3000.0}
                    //Employee{name='王五', age=26, salary=4500.0}
                    //Employee{name='麻子', age=30, salary=2700.0}
                    //Employee{name='张三', age=45, salary=8700.0}
        }
    
3、终止操作
  • 查找与匹配

    • allMatch 检查是否匹配所有元素
    • anyMatch 检查 是否至少匹配一个元素
    • noneMatch 检查是否没有匹配所有元素
    • findFirst 返回第一个元素
    • **findAny ** 返回当前流中任意元素
    • count 返回流中的总个数
    • max 返回流中最大值
    • min 返回流中最小值
        @Test
        public void test5(){
    
            //判断是不是年龄都是18岁
            boolean b = employees.stream()
                    .allMatch((e) -> e.getAge().equals(18));
    
            System.out.println(b);  //false
    
            //判断是否有是18岁的
            boolean b1 = employees.stream()
                    .anyMatch((e) -> e.getAge().equals(18));
    
            System.out.println(b1);   //true
    
            //判断是不是没有20岁的
            boolean b2 = employees.stream()
                    .noneMatch((e) -> e.getAge().equals(20));
    
            System.out.println(b2);  //true
    
            //找出工资最低的那个
            //Optional四个容器类,可以避免空指针异常
            Optional<Employee> first = employees.stream()
                    .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                    .findFirst();
    
            System.out.println(first.get());  //Employee{name='田七', age=15, salary=200.0}
    
            //随便找一个年龄为18的
            Optional<Employee> any = employees.stream()
                    .filter((e) -> e.getAge().equals(18))
                    .findAny();
            System.out.println(any.get());  //Employee{name='张三', age=18, salary=3000.0}
    
            //查看list中有多少个元素
            long count = employees.stream()
                    .count();
    
            System.out.println(count); //6
    
            //获取年龄最大的
            Optional<Employee> max = employees.stream()
                    .max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
    
            System.out.println(max.get());  //Employee{name='张三', age=45, salary=8700.0}
    
            //获取年龄最小的
            Optional<Employee> min = employees.stream()
                    .min((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
    
            System.out.println(min.get());  //Employee{name='田七', age=15, salary=200.0}
        }
    
  • 归约

    • reduce(T identity, BinaryOperator) 可以将流中元素反复结合起来,得到一个值
        @Test
        public void test6(){
    
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    
            //对集合元素求和
            Integer reduce = list.stream()
                    .reduce(0, (x, y) -> x + y);
    
            System.out.println(reduce); //55
    
            //求出工资总和
            Optional<Double> salary = employees.stream()
                    .map(Employee::getSalary)
                    .reduce(Double::sum);
    
            System.out.println(salary.get());  //22100.0
        }
    

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

  • 收集

    • collect 将流转换为其他形式,接收一个collector接口的实现,用于给Stream中元素汇总的方法
        @Test
        public void test7(){
    
            //将所有的名字放到一个集合中
            List<String> list = employees.stream()
                    .map(Employee::getName)
                    .distinct()
                    .collect(Collectors.toList());
    
            System.out.println(list.toString()); //[张三, 李四, 王五, 麻子, 田七]
            
             //可以进行分组   (按年龄分组)
            Map<Integer, List<Employee>> collect = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getAge));
            System.out.println(collect);
            
            //{18=[Employee{name='张三', age=18, salary=3000.0}, Employee{name='李四', age=18, salary=3000.0}], 26=[Employee{name='王五', age=26, salary=4500.0}], 45=[Employee{name='张三', age=45, salary=8700.0}], 30=[Employee{name='麻子', age=30, salary=2700.0}], 15=[Employee{name='田七', age=15, salary=200.0}]}
        }
    

    collect功能强大,可以转换为很多的形式

posted @ 2022-01-29 16:51  浪上了天  阅读(69)  评论(0编辑  收藏  举报