zoukankan      html  css  js  c++  java
  • Java8 新特性

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

    Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

    Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

    这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

    元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

    +--------------------+       +------+   +------+   +---+   +-------+
    | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
    +--------------------+       +------+   +------+   +---+   +-------+

     一、Stream 的三个操作步骤

    • 1. 创建Stream
    • 2. 中间操作
    • 3. 终止操作(终端操作)

      1.)创建 Stream 测试代码如下:

    package com.xq.stream;
    
    import com.xq.design.model.Employee;
    import org.junit.jupiter.api.Test;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Stream;
    
    public class TestStreamAPI1 {
        //创建 Stream
        @Test
        public void test1(){
            //1. 可以通过 Collection 系列集合提供的 stream() 或 parallelStream()
            List<String> list = new ArrayList<>();
            Stream<String> stream1 = list.stream();
    
            //2. 通过 Arrays 中的静态方法 stream() 获取数组
            Employee[] emps = new Employee[10];
            Stream<Employee> streame =  Arrays.stream(emps);
    
            //3. 通过 Stream 类中的静态方法 of()
            Stream<String> steam3 = Stream.of("aa","bb","cc");
    
            //4. 创建无线流
            // - 迭代
            Stream<Integer> stream4 = Stream.iterate(0,(x) -> x + 2);
            stream4.limit(10).forEach(System.out::println);
            // - 生成
            Stream.generate(() -> Math.random())
                    .limit(5)
                    .forEach(System.out::println);
        }
    
    }
    TestStreamAPI1 

    2)中间操作

    • 筛选与切片
    1. filter —— 接受 Lambda ,从流中抛出某些元素。
    2. limit --- 截断流,使其元素不超过给定数量。
    3. skip(n) --- 跳过元素,返回一个扔掉了前 n 个元素的流。 若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
    4. distinct --- 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
    • 映射
    1. map --- 接收 Lambda ,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
    2. flatMap --- 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流。
    • 排序
    1. sorted() ---- 自然排序(Comparable)
    2. sorted(Comparator com) ---- 定制排序

    测试代码如下:

    package com.xq.stream;
    
    import com.xq.design.model.Employee;
    import org.junit.jupiter.api.Test;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    import java.util.stream.Stream;
    
    /**
     * 中间操作
     */
    public class TestStreamAPI2 {
        List<Employee> employees = Arrays.asList(
                new Employee("张三",18,9999.99),
                new Employee("李四",58,8888.88),
                new Employee("王五",26,5555.55),
                new Employee("赵六",36,6666.66),
                new Employee("田七",12,3333.33),
                new Employee("赵六",36,6666.66),
                new Employee("赵六",36,6666.66)
        );
        
        //内部迭代:迭代操作由 Stream API 完成
        @Test
        public void test1(){
            // 中间操作:  不会执行任何操作
            Stream stream = employees.stream()
                    .filter((e) -> {
                        System.out.println("Stream API 的中间操作");
                        return e.getAge() > 35;
                    });
            // 终止操作:一次性执行全部内容,即“惰性求值”
            stream.forEach(System.out::println);
        }
    
        //外部迭代
        @Test
        public void test2(){
            Iterator<Employee> it = employees.iterator();
            while (it.hasNext()){
                System.out.println(it.next());
            }
        }
        
        /**
         *  筛选与切片
         *  filter —— 接受 Lambda ,从流中抛出某些元素。
         *  limit  --- 截断流,使其元素不超过给定数量。
         *  skip(n) --- 跳过元素,返回一个扔掉了前 n 个元素的流。 若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
         *  distinct --- 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
         */
        @Test
        public void test3(){
            employees.stream()
                    .filter((e) ->{
                        System.out.println("短路!");
                        return e.getSalary() > 7000;
                    })
                    .limit(2)
                    .forEach(System.out::println);
        }
        
        @Test
        public void test4(){
           employees.stream()
                   .filter((e) -> e.getSalary() > 5000)
                   .skip(2)
                   .forEach(System.out::println);
        }
        
        @Test
        public void test5(){
            employees.stream()
                    .filter((e) -> e.getSalary() > 5000)
                    .distinct()
                    .forEach(System.out::println);
        }
        
        /**
         * 映射
         * map --- 接收 Lambda ,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
         * flatMap --- 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流。
         */
        @Test
        public void test6(){
            List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
            list.stream()
                    .map((str) -> str.toUpperCase())
                    .forEach(System.out::println);
            System.out.println("------------------------------");
            employees.stream()
                    .map(Employee::getName)
                    .forEach(System.out::println);
            System.out.println("-----------------------------");
            Stream<Stream<Character>> stream = list.stream()
                    .map(TestStreamAPI2::filterCharacter);
            stream.forEach((sm) -> sm.forEach(System.out::println) );
            System.out.println("---------------------------");
            Stream<Character> sm = list.stream()
                    .flatMap(TestStreamAPI2::filterCharacter);
            sm.forEach(System.out::println);
        }
    
        public static Stream<Character> filterCharacter(String str){
            List<Character> list = new ArrayList<>();
            for(Character ch :str.toCharArray()){
                list.add(ch);
            }
            return list.stream();
        }
    
    
        /** 排序
         *  sorted() ---- 自然排序(Comparable)
         *  sorted(Comparator com) ---- 定制排序
         */
        @Test
        public void test7(){
            List<String> list = Arrays.asList("ccc","aaa","bbb","ddd","eee");
            list.stream()
                    .sorted()
                    .forEach(System.out::println);
            System.out.println("---------------------------------");
    
            employees.stream()
                    .sorted((e1,e2) ->{
                        if(e1.getAge() == e2.getAge()){
                            return e1.getName().compareTo(e2.getName());
                        } else {
                            return -e1.getAge().compareTo(e2.getAge());
                        }
                    }).forEach(System.out::println);
        }
    
    }
    TestStreamAPI2

     3)终止操作

    • 查找与匹配
    1. allMatch --- 检查是否匹配所有元素
    2. anyMatch --- 检查是否至少匹配一个元素
    3. noneMatch --- 检查时候没有匹配所有元素
    4. findFirst ---- 返回第一个元素
    5. findAny ---- 返回当前流中的任意元素
    6. count ---- 返回流中元素的总个数
    7. max ---- 返回流中最大值
    8. min ---- 返回流中的最小值
    • 规约
    1. reduce(T identity,BinaryOperator) / reduce(BinaryOperator) ---- 可以将流中元素反复结合起来,得到一个值。
    • 收集
    1. collection ---- 将流转换为其他形式,接受一个 Collection 接口的实现,用于给 Stream 中元素做汇总的方法

    测试代码如下:

    package com.xq.stream;
    
    import com.xq.design.model.Employee;
    import com.xq.design.model.Employee.Status;
    import org.junit.jupiter.api.Test;
    
    import java.util.*;
    import java.util.stream.Collectors;
    
    /**
     * 终止操作
     */
    public class TestStreamAPI3 {
        List<Employee> employees = Arrays.asList(
                new Employee("张三",18,9999.99, Status.FREE),
                new Employee("李四",58,8888.88, Status.BUSY),
                new Employee("王五",26,5555.55, Status.VOCATION),
                new Employee("赵六",36,6666.66, Status.FREE),
                new Employee("田七",12,3333.33, Status.BUSY),
                new Employee("田七",12,3333.33, Status.BUSY)
        );
        /**
         * 查找与匹配
         * allMatch --- 检查是否匹配所有元素
         * anyMatch --- 检查是否至少匹配一个元素
         * noneMatch --- 检查时候没有匹配所有元素
         * findFirst ---- 返回第一个元素
         * findAny ----  返回当前流中的任意元素
         * count ---- 返回流中元素的总个数
         * max ---- 返回流中最大值
         * min ---- 返回流中的最小值
         */
        @Test
        public void test1(){
            Boolean b1 = employees.stream()
                    .allMatch((e) -> e.getStatus().equals((Status.BUSY)));
            System.out.println(b1);
    
            Boolean b2 = employees.stream()
                    .anyMatch((e) -> e.getStatus().equals(Status.BUSY));
            System.out.println(b2);
    
            Boolean b3 = employees.stream()
                    .noneMatch((e) -> e.getStatus().equals(Status.BUSY));
            System.out.println(b3);
    
            Optional<Employee> op = employees.stream()
                    .sorted((e1,e2) -> -Double.compare(e1.getSalary(),e2.getSalary()))
                    .findFirst();
            System.out.println(op.get());
            Optional<Employee> op2 = employees.parallelStream()
                    .filter((e) -> e.getStatus().equals(Status.FREE))
                    .findAny();
            System.out.println(op2.get());
        }
        @Test
        public void test2(){
            Long count = employees.stream()
                    .count();
            System.out.println(count);
    
            Optional<Employee> op1 = employees.stream()
                    .max((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()));
            System.out.println(op1.get());
    
            Optional<Double> op2 = employees.stream()
                    .map(Employee::getSalary)
                    .min(Double::compare);
            System.out.println(op2.get());
        }
    
        /**
         * 规约
         * reduce(T identity,BinaryOperator) / reduce(BinaryOperator) ---- 可以将流中元素反复结合起来,得到一个值。
         */
        @Test
        public void test3(){
            List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    
            Integer sun = list.stream()
                    .reduce(0,(x,y) -> x+y);
            System.out.println(sun);
            System.out.println("----------------------");
    
            Optional<Double> op = employees.stream()
                    .map(Employee::getSalary)
                    .reduce(Double::sum);
            System.out.println(op.get());
        }
    
        /**
         * 收集
         * collection ---- 将流转换为其他形式,接受一个 Collection 接口的实现,用于给 Stream 中元素做汇总的方法。
         */
        @Test
        public void test4(){
            List<String> list = employees.stream()
                    .map(Employee::getName)
                    .collect(Collectors.toList());
            list.forEach(System.out::println);
            System.out.println("---------------------");
    
            Set<String> set = employees.stream()
                    .map(Employee::getName)
                    .collect(Collectors.toSet());
            set.forEach(System.out::println);
            System.out.println("----------------------");
    
            HashSet<String> hashSet = employees.stream()
                    .map(Employee::getName)
                    .collect(Collectors.toCollection(HashSet::new));
            hashSet.forEach(System.out::println);
        }
        @Test
        public void test5(){
            //总数
            Long count =employees.stream()
                    .collect(Collectors.counting());
            System.out.println(count);
    
            //平均值
            Double ave = employees.stream()
                    .collect(Collectors.averagingDouble((e) -> e.getSalary()));
            System.out.println(ave);
            //总和
            Double sum = employees.stream()
                    .collect(Collectors.summingDouble(Employee::getSalary));
            System.out.println(sum);
            //最大工资的员工
            Optional<Employee> max = employees.stream()
                    .collect(Collectors.maxBy((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary())));
            System.out.println(max.get());
            //最小工资
            Optional<Double> min = employees.stream()
                    .map(Employee::getSalary)
                    .collect(Collectors.minBy(Double::compare));
            System.out.println(min.get());
        }
        @Test
        public void test6(){
            //按照状态分组
            Map<Status,List<Employee>> map = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getStatus));
            System.out.println(map);
        }
        @Test
        public void test7(){
            //多级分组
            Map<Status,Map<String,List<Employee>>> map = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getStatus,Collectors.groupingBy((e) -> {
                        if(((Employee)e).getAge() <= 35){
                            return "二逼青年";
                        } else if(((Employee)e).getAge() <= 50){
                            return "中年";
                        } else {
                            return "老年";
                        }
                    })));
            System.out.println(map);
        }
        @Test
        public void test8(){
            //分区
            Map<Boolean,List<Employee>> map = employees.stream()
                    .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
            System.out.println(map);
        }
        @Test
        public void test9(){
            DoubleSummaryStatistics dss = employees.stream()
                    .collect(Collectors.summarizingDouble(Employee::getSalary));
            System.out.println(dss.getSum());
            System.out.println(dss.getAverage());
            System.out.println(dss.getMax());
        }
        @Test
        public void test10(){
            String str = employees.stream()
                    .map(Employee::getName)
                    .collect(Collectors.joining(",","==","=="));
            System.out.println(str);
        }
    }
    TestStreamAPI3

    本文来自博客园,作者:l-coil,转载请注明原文链接:https://www.cnblogs.com/l-coil/p/12898277.html

  • 相关阅读:
    随机数模块(random)
    时间模块(time)
    collection模块 1
    collection模块
    re模块
    正则
    Bootstrap 关于下拉菜单的使用
    Bootstrap 关于Glyphicons 字体图标的使用
    oracle拼音排序
    ajax缓存问题
  • 原文地址:https://www.cnblogs.com/xianquan/p/12898277.html
Copyright © 2011-2022 走看看