• java8新特性(二)StreamApi


    Stream的作用

    stream是java8中处理集合的关键抽象信息,它可以指定希望对集合进行的操作,可以执行查找、过滤和映射数据等操作。

    使用StreamApi对集合数据进行操作,就类似于使用使用sql对数据库操作。简而言之,StreamApi提供了高效且易于使用的数据处理方式。

    什么是流?

    流指的是用于操作数据源所生成的元素序列。

    需要注意的是:

    (1)stream不会自己存储元素;

    (2)不会改变源对象,会返回一个新的stream

    (3)stream是延迟执行的,意味着它们会等到需要结果的时候才会执行。

     Stream操作的三个步骤:

    (1)创建Stream

    一个数据源(集合、数组)获取一个流;

    (2)中间操作

    一个中间操作链,对数据源的数据进行处理;

    (3)终止操作

    一个终止操作,执行中间操作链,产生结果。

    案例

    流的获取方式

       @Test
        public void test01(){
            // 可以通过Collection集合提供stream()或parallelStearam()
            List<String > list = new ArrayList<>();
            Stream<String> stream = list.stream();
            //通过Arrays的静态方法stream()获取数组流
            Employee[] employee = new Employee[10];
            Stream<Employee> stream1 = Arrays.stream(employee);
            //通过stream类中的静态方法of()
            Stream<String > stream2 = Stream.of("aa","bb","cc");
    
            //创建无限流
            Stream<Integer> stream3 = Stream.iterate(0,(x)->x+2);
            stream3.limit(10).forEach(System.out::println);
            System.out.println("-------------------------------------");
            Stream.generate(()->Math.random()).limit(5).forEach(System.out::println);
        }

    中间操作与终止操作

        @Test
        public void test02(){
    
            List<Employee> employees = Arrays.asList(new Employee("张三",23),
                    new Employee("李四",24),
                    new Employee("王五",25),
                    new Employee("王五",25));
            //中间操作:不会执行任何操作
            Stream<Employee> stream = employees.stream().filter((e)->{
                System.out.println("Stream Api中间操作");
                return e.getAge()>24;
            });
            //终止操作:一次执行全部操作,
            stream.forEach(System.out::println);
            System.out.println("---------------------------------------");
            employees.stream().filter((e)->e.getAge()>22).skip(1).forEach(System.out::println);
            System.out.println("-------------");
            //使用distinct方法要重写equals和hashcode方法
            employees.stream().filter((e)->e.getAge()>22).distinct().forEach(System.out::println);
    
        }

    映射map方法和flatMap方法

        @Test
        public void test03(){
            List<String> strings = Arrays.asList("aaa","bbb","ccc");
            strings.stream().map((str)->str.toUpperCase()).forEach(System.out::println); //接收lambda操作,该函数将操作应用到每个元素上
            System.out.println("----------------------------------");
            employees.stream().map(Employee::getAge).forEach(System.out::println);
            System.out.println("----------------------------------");
            Stream<Stream<Character>> streamStream = strings.stream().map(StreamMain::filterChareacter);//map方法返回的是stream流
            streamStream.forEach((sm)->{
                sm.forEach(System.out::print); //需要嵌套for循环
            });
            System.out.println("----------------------------------");
            Stream<Character> characterStream = strings.stream().flatMap(StreamMain::filterChareacter);//flatMap返回的是元素
            characterStream.forEach(System.out::println);//不需要嵌套for循环
    
            //map和flatMap作用的对比类似于 add和addAll方法
            // Map是相当于把一个个流加入到当前流中,
            //FlatMap是相当于把一个个元素加入到当前流中。
            Collection<Object > aList = new ArrayList();
            Collection<Object > bList = new ArrayList();
            bList.add("13");
            bList.add("14");
            aList.add("12");
            aList.add(bList);
            System.out.println(aList);
        }
    
        //对字符串进行切分
        public static Stream<Character> filterChareacter(String str){
            List<Character> list = new ArrayList<>();
            for(Character ch :str.toCharArray()){
                list.add(ch);
            }
            return list.stream();
        }

    sorted方法

       List<Employee> employees = Arrays.asList(new Employee("张三",23),
                new Employee("李四",24),
                new Employee("王五",25),
                new Employee("王五",25));    
    
    @Test
        public void test04(){
            List<String > strings = Arrays.asList("aaa","ccc","bbb","ddd");
            strings.stream().sorted().forEach(System.out::println);
            //按年龄排序  如果年龄相同则按姓名排序
            employees.stream().sorted((e1,e2)->{
                if(e1.getAge()==(e2.getAge())){
                    return e1.getUserName().compareTo(e2.getUserName());
                }else {
                    return e1.getAge().compareTo(e2.getAge());
                }
            }).forEach(System.out::println);
        }

    allmatch方法

    @Test
        public void test05(){
           boolean flag = employees.stream().allMatch((e)->e.getAge().equals(25)); //检查是否匹配所有元素
            System.out.println(flag);
    
            boolean b2 = employees.stream().anyMatch((e)->e.getAge().equals(25));
            System.out.println(b2);
    
            boolean b3 = employees.stream().noneMatch((e)->e.getAge().equals(25));//检查所有元素是否都不匹配
            System.out.println(b3);
    
            Optional<Employee> first = employees.stream().sorted((e1, e2) ->
                    -Integer.compare(e1.getAge(), e2.getAge())
            ).findFirst();
            System.out.println(first);
    
            Optional<Employee> any = employees.parallelStream().filter((e) -> e.getAge().equals(24)).findAny();
            System.out.println(any);;
        }

    count方法

        @Test
        public void test06(){
            Optional<Integer> min = employees.stream().map(Employee::getAge).min(Integer::compare);
            System.out.println(min);
    
            Optional<Employee> max = employees.stream().max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
            System.out.println(max);
    
            long count = employees.stream().count();
            System.out.println(count);
        }

    reduce 规约

        //reduce 规约
        //可以将流中的元素反复结合起来,得到一个值
        @Test
        public void test07(){
            List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
            Integer sum = nums.stream().reduce(0, (x, y) -> x + y);
            System.out.println(sum);
    
            Optional<Integer> sumInt = employees.stream().map(Employee::getAge)
                    .reduce(Integer::sum);
            System.out.println(sumInt.get());
        }

    collect方法

       //collect可以将流转化为其他形式
        @Test
        public void test08(){
            List<String> collect = employees.stream().map(Employee::getUserName)
                    .collect(Collectors.toList());
            System.out.println(collect);
            System.out.println("----------------------");
            Set<String> collectSet = employees.stream()
                    .map(Employee::getUserName)
                    .collect(Collectors.toSet());
            collectSet.forEach(System.out::println);
            System.out.println("---------------------------");
            HashSet<String> collect1 = employees.stream().map(Employee::getUserName)
                    .collect(Collectors.toCollection(HashSet::new));
            collect1.forEach(System.out::println);
        }
    
        @Test
        public void test09(){
            //总数
            Long collect = employees.stream()
                    .collect(Collectors.counting());
            System.out.println(collect);
            //平均数
            Double avg = employees.stream()
                    .collect(Collectors.averagingInt(Employee::getAge));
            System.out.println(avg);
            //总和
            Integer sum = employees.stream()
                    .collect(Collectors.summingInt(Employee::getAge));
            System.out.println(sum);
        }

    maxBy、minBy方法

        @Test
        public void test10(){
            Optional<Employee> collect = employees.stream()
                    .collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
            System.out.println(collect.get());
    
            Optional<Integer> collect1 = employees.stream().map(Employee::getAge)
                    .collect(Collectors.minBy(Integer::compare));
            System.out.println(collect1.get());
        }

    分组

    @Test
        public void teset01(){
            //按照某个属性分组
            Map<Integer, List<Employee>> collect = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getAge));
            System.out.println(collect);
            System.out.println("----------------------------------");
            //多级分组
            Map<Integer, Map<String, List<Employee>>> collect1 = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy((e) -> {
                        if (((Employee) e).getSalary() > 24000) {
                            return "有钱人";
                        } else {
                            return "没钱人";
                        }
                    })));
            System.out.println(collect1);
        }

    分区

        //分区
        @Test
        public void test02(){
            Map<Boolean, List<Employee>> collect = employees.stream()
                    .collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000));
            System.out.println(collect);
        }
  • 相关阅读:
    面向对象设计原则之接口隔离原则
    面向对象设计原则之开闭原则
    [OOD]违反里氏替换原则的解决方案
    错误程序
    error: ‘for’ loop initial declarations are only allowed in C99 mode
    函数模板
    查找
    队列类模板
    栈类模板
    单链表的结点类模板
  • 原文地址:https://www.cnblogs.com/menbo/p/13696637.html
Copyright © 2020-2023  润新知