• java8新特性之stream流


    Stream 流是 Java 8 提供给开发者一套新的处理集合的API,他把我们将要处理的集合作为流,就像流水线一样,我们可以对其中的元素进行筛选,过滤,排序等中间操作,只不过这种操作更加简洁高效。

    Stream的创建:
    • 1.可以通过Collection系列的集合提供的stream()或者parallelStream()方法,集合的stream方法创建的是串行流,parallelStream方法创建的是并行流(并行流就是多线程进行操作,这个时候就要考虑线程安全问题了)
    • 2.可以通过Arrays.stream()获取数组流
    • 3.通过Stream类中的静态方法of()可以创建流对象
    • 当创建一个无限流使用Stream.iterate()方法,是一个死循环

    //Stream 的创建

    
        //1.通过集合的stream()方法创建串行流
        ArrayList<Object> list = new ArrayList<>();
        Stream<Object> stream = list.stream();
        //2.也可以通过集合的parallelStream创建并行流
        Stream<Object> parallelStream = list.parallelStream();
        //3.通过Arrays.stream(T[] t),将数组转换成流
        IntStream stream1 = Arrays.stream(new int[10]);
        //4.通过Stream的静态方法of创建流
        Stream<String> stringStream = Stream.of("aaa", "bbb", "ddd", "ccc");
        
        //创建无限流 迭代   
        Stream<Integer> iterate = Stream.iterate(1, (x) -> x + 2);
        iterate.limit(10).forEach(System.out::println);//生成奇数从一开始往后的10位
    
        //生成
        Stream.generate(()->(int)(Math.random()*100))//随机生成10个100以内的int类型数
                .limit(10)
                .forEach(System.out::println);
    
    Stream的中间操作

    多个中间操作可以连接起来形成一个流水线,除非流水线线上触发终止操作,否则中间操作就不会执行任何处理,并不会显示处理结果。而在终止操作时一次性全部处理,称为惰性求值。

    • 筛选与切片

    filter-接收Lambda,从流中排除某些元素
    limit–截断流,使其元素不超过给定数量
    skip(n) – 跳过元素,返回一个扔掉了前n个元素的流。若流中的元素个数小于n,则返回null,与limit()互补
    distinct–筛选通过流所生成元素的hashCode(),equals()方法来去掉重复的元素

    public class StreamAPITest {
        List<Employee> employees = Arrays.asList(
                new Employee("小明", 12000, 32),
                new Employee("小红", 8000, 23),
                new Employee("小刚", 5000, 19),
                new Employee("小凉", 7000, 40),
                new Employee("小凉", 7000, 40),
                new Employee("小凉", 7000, 40)
        );
    
        @Test
        public void test2() {
            //filter是内部迭代,
            //也就是StreamAPI内部实现的迭代不需要使用者再次手写迭代
            employees.stream()
                    .filter((e) -> {
                        //System.out.println("进入过滤器");
                        return e.getSalary() > 7000.0;
                    })
                    .forEach((e) -> System.out.println(e.getSalary()));
            System.out.println("-----------------------");
    
    
            //测试limit(n)取前n个元素
            employees.stream()
                    .limit(3)
                    .forEach((e) -> System.out.println(e));
    
            System.out.println("-----------------------");
            //skip(n)测试  舍掉前n个元素,去剩下后面的
            employees.stream()
                    .skip(3)
                    .forEach((e) -> System.out.println(e));
    
    
            System.out.println("=============================");
            //distinct()去除重复,按照streamAPI中的hashCode和equals方法
            employees.stream()
                    .distinct()
                    .forEach((e) -> System.out.println(e));
        }
    }
    

    注意:distinct方法去除重复,需要实现pojo的hashCode()和equals().
    控制台输出:

    12000.0
    8000.0
    -----------------------
    Employee{name='小明', salary=12000.0, age=32}
    Employee{name='小红', salary=8000.0, age=23}
    Employee{name='小刚', salary=5000.0, age=19}
    -----------------------
    Employee{name='小凉', salary=7000.0, age=40}
    Employee{name='小凉', salary=7000.0, age=40}
    Employee{name='小凉', salary=7000.0, age=40}
    =============================
    Employee{name='小明', salary=12000.0, age=32}
    Employee{name='小红', salary=8000.0, age=23}
    Employee{name='小刚', salary=5000.0, age=19}
    Employee{name='小凉', salary=7000.0, age=40}
    

    映射
    map——接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
    flatMap——接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流。

    public static Stream<Character> getCharacter(String str) {
        List<Character> list = new ArrayList<>();
    
    
        for (Character character : str.toCharArray()) {
            list.add(character);
        }
        return list.stream();
    }
    
    @Test
    public void test3() {
        /**
         * map,flapMap
         */
    
        List<String> list = Arrays.asList("cvt", "aer", "ktv", "dbms");
    
        //1.将list中的每个元素都转换成大写
        list.stream()
                .map((e) -> e.toUpperCase())
                .forEach(System.out::println);
    
        System.out.println("------水平分割线---------");
        //2.取出employees中的每个员工姓名输出
        employees.stream()
                .map((e) -> e.getName())
                .forEach(System.out::println);
        System.out.println("------水平分割线---------");
    
        Stream<Character> sm = list.stream()
                .flatMap(StreamAPITest::getCharacter);
    
        sm.forEach(System.out::println);
    
    }
    
    排序

    这个默认的是从小到大,可以自定义排序

    //排序
        List<Integer> list = Arrays.asList(12, 32, 2, 45, 38, 29);
    
        list.stream()
                .sorted()
                .forEach(System.out::println);//默认排序,从小到大
    
        System.out.println("-------------------------");
    
    
        //定制排序 employees 先按照月薪排序,如果月薪相等按照年龄排序
    
    
        employees.stream()
                .sorted((e1, e2) -> {
                    if (e1.getSalary() == e2.getSalary()) {
                        return e1.getAge().compareTo(e2.getAge()) ;
                    } else {
                        return e1.getSalary().compareTo( e2.getSalary());
                    }
                })
                .forEach(System.out::println);
    

    运行结果:

    12
    29
    32
    38
    45
    -------------------------
    Employee{name='小刚', salary=5000.0, age=19}
    Employee{name='小凉', salary=7000.0, age=40}
    Employee{name='小谷', salary=7000.0, age=20}
    Employee{name='小红', salary=8000.0, age=23}
    Employee{name='小明', salary=12000.0, age=32}
    
    查找与匹配

    allMatch ——检查是否匹配所有元素
    anyMatch——检查是否至少匹配一个元素
    noneMatch——检查是否没有匹配所有元素
    findFirst——返回第一个元素
    findAny——返回当前流中的任意元素
    count——返回流中元素的总个数
    max——返回流中最大值
    min——返回流中最小值

    
    private List<Employee> employees = Arrays.asList(
            new Employee("小明", 12000.0, 32, Employee.Status.VOCATION),
            new Employee("小红", 8000.0, 23, Employee.Status.FREE),
            new Employee("小刚", 5000.0, 19, Employee.Status.BUSY),
            new Employee("小凉", 7000.0, 40, Employee.Status.BUSY),
            new Employee("小谷", 7000.0, 20, Employee.Status.FREE)
    );
    
    
    //匹配、查找、最大值、最小值、
    @Test
    public void test5() {
        //allMatch,如果所有的元素都匹配返回true,否则返回false
        boolean b1 = employees.stream()
                .allMatch((e) -> {
                    return e.getStatus() == Employee.Status.BUSY;
                });
        System.out.println("b1 = " + b1);
    
        //anyMatch 匹配中的任意元素满足条件返回true
        boolean b2 = employees.stream()
                .anyMatch((e) -> e.getStatus() == Employee.Status.VOCATION);
        System.out.println("b2 = "+b2);
    
        //noneMatch 如果所有元素都满足条件返回true,否则返回false
        boolean b3 = employees.stream()
                .noneMatch((e) -> e.getStatus() == Employee.Status.FREE);
            //并不是所有的员工状态都是free所以返回false
        System.out.println("b3 = "+b3);
    
        //findFirst 查找第一个元素
        Optional<Employee> employee1 = employees.stream()
                .sorted((e1,e2)->-e1.getSalary().compareTo(e2.getSalary()))//salary 从高到低,返回最高工资的员工对象
                .findFirst();
        System.out.println("firstSalaryEmployee : "+employee1);
    
        //findAny 返回当前流中任意一个元素
        Optional<Employee> any = employees.parallelStream()//parallelStream 并行流
                .findAny();
        System.out.println("any : "+any);
    
        //max
        Optional<Employee> max = employees.stream()
                .max((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
        System.out.println("max age employee "+max);
    
        //min
        Optional<Employee> min = employees.stream()
                .min((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
        System.out.println("min age employee "+min);
    
        //count
        long count = employees.stream()
                .count();
        System.out.println("count: "+count);
    }
    
    
    
    运行结果输出:
    
    b1 = false
    b2 = true
    b3 = false
    firstSalaryEmployee : Optional[Employee{name='小明', salary=12000.0, age=32}]
    any : Optional[Employee{name='小刚', salary=5000.0, age=19}]
    max age employee Optional[Employee{name='小凉', salary=7000.0, age=40}]
    min age employee Optional[Employee{name='小刚', salary=5000.0, age=19}]
    count: 5
    
    归约

    reduce(T identity,BinaryOperator)
    reduce(BinaryOperator)
    作用:可以将流中元素反复结合起来,得到一个值。

    List<Integer> list = Arrays.asList(23,12,3,45,67,29,98);
    Integer sum = list.stream()
            .reduce(0, (x, y) -> x + y);
    System.out.println("sum = "+sum);
    
    //先从employees中取出salary,然后reduce做处理,将员工工资求和
    Optional<Double> optionalDouble = employees.stream()
            .map(Employee::getSalary)
            .reduce(Double::sum);
    
    System.out.println(optionalDouble.get());
    

    收集
    collect——将流转成其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。

    public void test7(){
        //收集员工名字返回集合
    
        //返回List
        List<String> names = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        names.forEach(System.out::println);
        //返回指定集合
        HashSet<String> strings = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(strings);
    
    }
    
    结果:
    小明
    小红
    小刚
    小凉
    小谷
    [小刚, 小凉, 小谷, 小明, 小红]
    

    使用collect从employees 中获取最大工资的人,最小工资,平均工资,员工工资总和,员工人数

    @Test
    public void test1() {
        //count
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println("count = " + count);
    
        //max employee
        Optional<Employee> maxSalary = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(maxSalary.get());
    
        //min
        Optional<Employee> minSal = employees.stream()
                .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(minSal.get());
    
        //avg salary
        Double avgSal = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println("avg salary = "+avgSal);
    
        //sum salary
        Double sumSal = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println("sum salary = "+sumSal);
    }
    
    输出结果:
    

    count = 5
    Employee{name=‘小明’, salary=12000.0, age=32}
    Employee{name=‘小刚’, salary=5000.0, age=19}
    avg salary = 7800.0
    sum salary = 39000.0

    分组

    @Test
    public void test2(){
    
        String collect = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",","---","---"));//将取出的name连接在一起,中间用,隔开,前缀是‘---’,后缀也是'---'.
    
        System.out.println(collect);
    
        Map<Employee.Status, List<Employee>> collect1 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println("按状态分组:"+collect1);
    }
    

    输出结果:
    —小明,小红,小刚,小凉,小谷—
    按状态分组:{BUSY=[Employee{name=‘小刚’, salary=5000.0, age=19}, Employee{name=‘小凉’, salary=7000.0, age=40}], VOCATION=[Employee{name=‘小明’, salary=12000.0, age=32}], FREE=[Employee{name=‘小红’, salary=8000.0, age=23}, Employee{name=‘小谷’, salary=7000.0, age=20}]}

  • 相关阅读:
    problems_mysql
    skills_mysql
    knowledge_mysql
    knowledge_impala
    oozie的常见错误
    problems_kafka
    problems_flume
    kafka在zookeeper默认使用/为根目录,将/更换为/kafka
    java学习笔记总略
    大公司怎么开发和部署前端代码——作者:张云龙[知乎兴趣转载]
  • 原文地址:https://www.cnblogs.com/itjiangpo/p/14181429.html
Copyright © 2020-2023  润新知