Java8 特性

一:Lambda表达式
    理解:
        Lambda表达式相当于代替匿名内部类的,但要求:匿名内部类实现的接口中只有一个抽象方法  

    应用场景:
        Lambda表达式同匿名内部类的应用场景,一般作为接口的实例传递给方法
        直接做为接口的实例赋值给接口

    注意事项:
        ①参数类型可以省略
        ②如果Lambda体中只有一句话,则大括号也可以省略
        ③如果Lambda体中只有一句话而且是return语句,则return也可以省略
        ④如果只有一个参数,则小括号也可以省略

    @Test
    public void test2() {
        //匿名内部类
        Comparator<String> c1 = new Comparator<String>() {
            
            @Override
            public int compare(String o1, String o2) {
                System.out.println("");
                return o1.compareTo(o2);
            }
        };

        //Lambda
        
        Comparator<String> c2 = ( o1, o2)-> o1.compareTo(o2);
        
    }



二:函数式接口

    常用函数:
  1. * 消费型接口Consumer
  2. * 供给型接口Supplier
  3. * 函数型接口Function
  4. * 断定型接口Predicate


    //测试:消费型接口Consumer
    @Test
    public void test1() {
        Consumer<Integer> con2 = t->{
            if (t>1000) {
                System.out.println("吃大烤鸭");
            }else{
                System.out.println("吃肉夹馍");
            }
        };
        con2.accept(2000);
    }


    //测试供给型接口Supplier
    @Test
    public void test2() {
         Supplier <String> sup = ()->"john".toUpperCase();
        System.out.println(sup.get());

    }



    //测试函数型接口Function
    @Test
    public void test3() {
         Function <Double,Double> fun = d->Math.pow(d, 2);
        
        System.out.println(fun.apply(100d));
    }


    
    //测试断定型接口Predicate
    @Test
    public void test4() {
        
         Predicate <Employee> pre = e->e.getName().contains("a");
        
        System.out.println(pre.test(new Employee("john", 12, 1000, '女')));

    



三、各类引用
   
    1、方法引用
    理解:
        满足一定条件的Lambda表达式的代替,也是作为函数式接口的实例出现!
        方法引用仅仅是Lambda表达式的语法糖形式,提高语义性和阅读性
    

     要求:
        1、Lambda体中只有一句话
        2、仅有的这一句话为方法的调用
        3、调用的方法中的参数列表和返回 ,与实现的抽象方法的参数列表和返回一致!

        如果是类名调用普通方法,则要求:抽象方法的第一次参数为调用方法的调用者,其他参数类型一致!

    //测试形式1:对象::普通方法
    @Test
    public void test1() {
        //使用Lambda表达式
        Consumer<String> con = s->System.out.println(s);
        
        //使用方法引用
        
        Consumer<String> con2 = System.out::println;
        con2.accept("hello");

    }


    //测试形式2:类::静态方法
    
    @Test
    public void test2() {
        
        //使用Lambda表达式
        Comparator<Integer> com1 = (i1,i2)->Integer.compare(i1, i2);
        Comparator<Double> com3 = (i1,i2)->Double.compare(i1, i2);
        
        //使用方法引用
        Comparator<Integer> com2 = Integer::compare;
        Comparator<Double> com4 = Double::compare;

    }


    //测试形式3:类::普通方法
    @Test
    public void test3() {
        
        //使用匿名内部类
        Comparator<String> com1 = new Comparator<String>(){

            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
            
        };
        
        //使用Lambda表达式
        Comparator<String> com2 = (o1,o2)->o1.compareTo(o2);
                 
        //使用方法引用
        Comparator<String> com3 = String::compareTo;

    }


    2、构造器引用
     理解:
        构造器引用 相当于对满足一定条件的Lambda表达式的简化

    条件:
        1、Lambda体中仅仅只有一句话
        2、Lambda体中仅有的一句话为通过调用构造器创建对象
        3、构造器的参数列表和抽象方法的参数列表保持一致。抽象方法的返回类型正好为该对象的类型!

    
    //案例1:String s = new String();
    @Test
    public void test1() {
        //使用匿名内部类
        Supplier<String> sup1 = new Supplier<String>(){

            @Override
            public String get() {
                return new String();
            }
            
        };
        
        //使用构造器引用
        Supplier<String> sup2 = String::new;

    }

    //案例2:String s = new String("hello");
    @Test
    public void test2() {
        //使用匿名内部类
        Function<String,String> fun1 = new Function<String,String>(){

            @Override
            public String apply(String t) {
                return new String(t);
            }
            
        };
        
        //使用构造器引用
        
        Function<String,String> fun2 = String::new;
        
    }


    //案例3: Employee emp = new Employee(String name, int age, double salary, char sex);
    @Test
    public void test3() {
        
        //使用匿名内部类
        A<String,Integer,Double,Character,Employee> a = new A<String,Integer,Double,Character,Employee>(){

            @Override
            public Employee method(String t, Integer r, Double m, Character u) {
                return new Employee(t,r,m,u);
            }
            
        };
        
        //使用构造器引用
        
        A<String,Integer,Double,Character,Employee> b = Employee::new;

    }
    interface A<T,R,M,U,V>{
        V method(T t,R r,M m,U u);
    }


    3、 数组引用
    理解:
        数组引用相当于满足一定条件的Lambda表达式的代替,也是作为函数式接口的实例出现

    要求:
        1、Lambda体中仅仅只有一句话
        2、仅有的一句话为创建数组对象
        3:抽象方法的参数类型为数组的长度类型,返回类型为创建的数组类型

    //案例1:return new String[5];    
    /*
     * 返回类型:String[]
     * 参数类型:Integer
     */
    @Test
    public void test1() {
        //使用匿名内部类
        Function<Integer,String[]> fun1 =  new Function<Integer,String[]>(){

            @Override
            public String[] apply(Integer t) {
                return new String[t];
            }
            
        };
        
        //使用数组引用
        
        Function<Integer,String[]> fun2 = String[]::new;

    }



    //案例2:return new StringBuffer[6];
    @Test
    public void test2() {
        Function<Integer,StringBuffer[]> fun = StringBuffer[]::new;
        
    }



四,Stream API

注意:
    1、分为三部进行执行,如果不执行最后的最后一步终止前面则不会执行
    2、Stream为“一次性消费”,即创建一次只能是使用一次。



    1、开始操作(创建Stream对象指向一个具体的数据源)
        此类用于演示Stream的开始操作:
            方式一:根据集合获取Stream对象  (数据源:集合)
            方式二:根据数组获取Stream对象  (数据源:数组)
            方式三:根据一组序列值获取Stream对象(数据源:一组值)
            方式四:创建无限流,根据一个规则获取Stream对象(数据源:自定义规则)

    //方式一:根据集合获取Stream对象  (数据源:集合) ★
    @Test
    public void test1() {
        
        List<Employee> list = EmployeeData.getEmployees();
        //获取串行流对象
        Stream<Employee> stream = list.stream();
        
        //获取并行流对象
        Stream<Employee> parallelStream = list.parallelStream();
        
        //终止操作
        //使用匿名内部类:
//        stream.forEach(new Consumer<Employee>(){
//
//            @Override
//            public void accept(Employee t) {
//                System.out.println(t);
//            }
//            
//        });
        
        //使用Lambda表达式:
        
//        stream.forEach(t->System.out.println(t));
        
        //使用方法引用:
        
        stream.forEach(System.out::println);

    }

    //方式二:根据数组获取Stream对象  (数据源:数组)
    @Test
    public void test2() {
        
        String[] arr = {"john","lucy","lily"};
//        Stream<String> stream = Arrays.stream(arr);
//        
//        stream.forEach(System.out::println);
        
        Arrays.stream(arr).forEach(System.out::println);

    }

    // 方式三:根据一组序列值获取Stream对象(数据源:一组值)
    @Test
    public void test3() {
        
        Stream<Character> of = Stream.of('a','b','c','d');
        
        of.forEach(System.out::println);

    }

    //方式四:生成无限流
    @Test
    public void test4() {
        //匿名内部类
//        Stream<Double> generate = Stream.generate(new Supplier<Double>(){
//
//            @Override
//            public Double get() {
//                return Math.random();
//            }
//            
//        });
//        
        //Lambda
//        Stream<Double> generate2 = Stream.generate(()->Math.random());
        
        //方法引用
        
        Stream<Double> generate3 =  Stream.generate(Math::random);
        
        generate3.forEach(System.out::println);

    }


     2 Stream的中间操作
        *中间操作可以形成流水线操作
        
    常见方法:
        filter(Predicate p)——接收 Lambda , 从流中排除某些元素。
        limit(n)——截断流,使其元素不超过给定数量。
        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
        map(Function<元素类型,R>)——映射,根据元素本身一一映射成新的元素
        flatMap(Function<元素类型,Stream>)——映射
        sorted()——自然排序
        sorted(Comparator)——定制排序

    List<Employee> list;
    @Before
    public void before(){
         list = EmployeeData.getEmployees();
    }



    //筛选与切片
    @Test
    public void test1() {
        
        //1.获取Stream对象
        Stream<Employee> stream = list.stream();
        
        //2.中间操作
        //filter:根据条件过滤
//        Stream<Employee> filter = stream.filter(t->t.getAge()>30);
        //limit:用于限制最大元素个数
//        Stream<Employee> limit = stream.limit(50);
        //skip:跳过指定的个数
//        Stream<Employee> skip = stream.skip(3);
        //distinct:去重
        Stream<Employee> distinct = stream.distinct();

        //3.终止操作
        distinct.forEach(System.out::println);

    }

    //测试:映射
    @Test
    public void test2() {
        
        //1.获取Stream对象
        Stream<Employee> stream = list.stream();
        
        //2.中间操作
        //map:映射
//        Stream<String> map = stream.map(new Function<Employee,String>(){
//
//            @Override
//            public String apply(Employee t) {
//                return t.getName();
//            }});
        
//        Stream<String> map = stream.map(Employee::getName);
        
        //flatMap:映射
        //使用匿名内部类:
//        stream.flatMap(new Function<Employee,Stream<Object>>(){
//
//            @Override
//            public Stream<Object> apply(Employee t) {
//                return TestStreamMiddle.employeeToStream(t);
//            }
//            
//        });
        
        //使用方法引用
        
        Stream<Object> flatMap = stream.map(TestStreamMiddle::employeeToStream);
        
        //3.终止操作
        
        flatMap.forEach(System.out::println);

    }

    //测试排序
    @Test
    public void test3() {

        //1.获取stream对象
        Stream<Employee> stream = list.stream();
        
        //2.中间操作
        
        //sorted():根据元素本身的比较性实现自然排序
        
//        Stream<Employee> sorted = stream.sorted();
        //sorted(comparator):根据比较器实现定制排序
        
        //进阶1:使用匿名内部类
//        stream.sorted(new Comparator<Employee>(){
//
//            @Override
//            public int compare(Employee o1, Employee o2) {
//                return Double.compare(o2.getSalary(), o1.getSalary());
//            }
//            
//        });
        //进阶2:使用Lambda
        
        Stream<Employee> sorted2 = stream.sorted((o1,o2)->Double.compare(o2.getSalary(), o1.getSalary()));
        
        
        
        //3.终止操作
        
        sorted2.forEach(System.out::println);
    }
    //自定义规则实现:将员工转换成Stream类型
    public static Stream<Object> employeeToStream(Employee e){
        Stream<Object> of = Stream.of(e.getName(),e.getAge(),e.getSalary(),e.getSex());
        return of;
    }


    3、Stream的终止操作
        常见方法:
            count:统计个数
            max(Comparator):求最大值
            min(Comparator):求最小值
            forEach(Consumer):内部迭代
            reduce(BinaryOperator<T>):归约、合并


    List<Employee> list;
    @Before
    public void before(){
         list = EmployeeData.getEmployees();
    }


    //测试:count  统计Stream中的元素个数
    @Test
    public void test1() {
        //1.获取stream对象
        Stream<Employee> stream = list.stream();
        
        //2.终止操作
        
        long count = stream.count();
        System.out.println(count);

    }

    //测试:max/min  获取Stream中的最大值或最小值
    @Test
    public void test2() {
        //1.获取stream对象
        Stream<Employee> stream = list.stream();
        
        //2.终止操作
        
//        Optional<Employee> max = stream.max((e1,e2)->Integer.compare(e1.getAge(), e2.getAge()));
        Optional<Employee> min = stream.min((e1,e2)->Integer.compare(e1.getAge(), e2.getAge()));
        
        System.out.println(min);

    }

    //测试:forEach 获取Stream中的内部迭代
    @Test
    public void test3() {
        //1.获取stream对象
        Stream<Employee> stream = list.stream();
        
        //2.终止操作
        stream.forEach(System.out::println);
        
    }

    //测试:reduce 归约,合并
    @Test
    public void test4() {
        //1.获取stream对象
        Stream<Employee> stream = list.stream();
        
        //2.终止操作
        /*
         * BinaryOperator:
         * T apply(T t1,T t2);
         */
        
        //进阶1:匿名内部类:
//        stream.reduce(new BinaryOperator<Employee>(){
//
//            @Override
//            public Employee apply(Employee t, Employee u) {
//                return null;
//            }
//            
//        });
        Stream<Double> map = stream.map(e->e.getSalary());
                
        
        Optional<Double> reduce = map.reduce((t,u)->t+u);
        System.out.println(reduce);
        
    }



五:Optional类
    主要是为了减少空指针异常



































  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值