Java8新特性

前言

最近在做笔试与看一些框架的底层源码的时候,会考察和使用到Java8的某些新特性,因此感觉系统地学习下Java8的新特性是很有必要的,于是有了这篇文章。

Java8新特性

Lambda表达式

Lambda表达式是什么?

Lambda表达式其实本质是一个匿名内部类,当某个接口只定义了唯一一个抽象方法(功能单一)时,我们就可以使用(参数) - > {抽象方法的实现} 来作为这个接口的实例来使用。

为什么要使用Lambda表达式?

Lambda表达式能够使代码更加简洁。()中的参数类型可以不写;当参数只有一个时,()也可以忽略;当抽象方法的实现代码只有一行时,{}和return和;可以同时省略,注意需要同时省略。

函数式接口

什么叫函数式接口?
Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,java不但可以支持OOP还可以支持OOF(面向函数编程)!
简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

四大函数式接口

接口类型接口介绍
Consumer消费型接口定义的唯一抽象方法是accept(T t) : 代表对参数类型T的变量进行操作,无返回值
Supplier供给型接口定义的唯一抽象方法是T get() : 代表获得一个返回参数类型为T的变量
Function<T,R>函数型接口定义的唯一抽象方法是R apply(T t) : 通过传入T类型的对象,返回一个R类型对象
Predicate断定型接口定义的唯一抽象方法是boolean test(T t) :通过自定义的规程对传入的T类型变量进行判断,返回true Or false

函数式接口的作用:它其实也是一种解耦的思想,当我们需要定义不同的规则时,只需要把规则传进去即可,而不需要去定义不同的方法实现,使用比较灵活。这个会在后面的Stream流中有所体现。

方法引用与构造器引用

一句话总结: 使用现成的方法代替Lambda表达式
使用方法: ①类 :: 静态方法名 ② 实例对象 :: 实例方法名
其实Lambda表达式主要传递的是一个方法的参数和方法的实现,那只要我把现成方法传递过去,自然也能够通过获得现成方法的参数和实现来进行传递,本质是一个意思。

Stream流

Stream 流是真正地把函数式编程风格引入Java中,它的引入能够像Mysql数据库一样轻松地实现对集合数据的复杂操作,也可以利用Stream API来对数据进行并行操作。

操作步骤:
①创建一个Stream流
一般采用list.stream() 获取顺序流 或者 采用list.parallelStream() 来获取并行流。(并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。与Fork/join框架类似:将一个大的任务,进行拆分(fork)成若干个小任务(拆到足够小时),再利用线程池中的线程将一个个的小任务进行运算,再将结果进行join汇总。)
②定义Stream流的一些中间操作
对流中的数据进行过滤或者修改操作: 过滤操作filter(Predicate p) , 去重操作distinct(), 截断操作limit(int count) , (接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素)映射操作map(Function f) ,排序操作sorted(Comparator c)等
③终止操作(只有在终止操作执行时,中间操作才会执行
一些常用的终止操作: 找出流中的最大值与最小值:max(Comparator c) 和 min(Comparator c) ; 遍历流中的每个元素foreach(Consumer c);流中是否存在某个元素anyMatch(Precidate p)等

Optional类

Optional类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。

示例代码:

public interface Car {
    void run();
}
public interface Caculator {
    int caculate(int num1,int num2);
}
public static void main(String[] args) {
        //lambada表达式测试
        //testLambda1();
        //testLambda2();

        //四大常用函数型接口测试
        //①消费型接口测试

        //testConsumer();
        //②供给型接口测试

        //testSupplier();
        //③函数型接口测试

        //testFunction();
        //④断定型接口测试

        //testPredicate();

        //Stream流测试
        //testStream();
    }
    //无参数无返回值
    private static void testLambda1(){
//        匿名内部类的写法
//        Car car = new Car(){
//            @Override
//            public void run() {
//                System.out.println("Car准备启动");
//            }
//        };
        Car car = ()->System.out.println("Car准备启动!!!");
        car.run();
    }
    //有参数有返回值
    private static void testLambda2(){
        Caculator caculator1 = (n1,n2)->n1-n2;
        int result1 = caculator1.caculate(3,2);

        Caculator caculator2 = (n3,n4)->n3*n4;
        int result2 = caculator2.caculate(3,4);

        System.out.println(result1);
        System.out.println(result2);
    }
     //消费型接口测试
    private static void testConsumer(){
        function1(10,(money)->System.out.println("小汽车花了我" + money + "dollar"));
    }
    private static void function1(int money, Consumer<Integer> con){
        con.accept(money);
    }
    //供给型接口测试
    private static void testSupplier(){
        String result = function2(()-> "I get this!");
        System.out.println(result);
    }
    private static String function2(Supplier<String> supplier){
        return supplier.get();
    }
    //函数型接口测试
    private static void testFunction(){
        String result = function3(10,(age)-> "I am "+age + " years old");
        System.out.println(result);
    }
    private static String function3(Integer age, Function<Integer,String> function){
        return function.apply(age);
    }
    //断定型接口测试
    private static void testPredicate(){
        boolean result = function4(20,(num)-> num > 10);
        System.out.println(result);
    }
    private static boolean function4(Integer number , Predicate<Integer> predicate){
        return predicate.test(number);
    }
    //Stream流测试
    private static void testStream(){

        List<Integer> list = Arrays.asList(1,5,7,9,3,4,2,22,12,15);
        Stream<Integer> stream = list.stream();
        //获取该列表中最大的三个数字,并把它们输出
        stream.sorted((num1,num2)->num2-num1).limit(3).forEach(System.out::println);

        System.out.println("-------------------------------------------------");
        //将列表中大于5的数字筛选出来,将它们的值都乘2,取最大的三个
        //此处结合了函数式接口,filter方法需要一个断定型接口Predicate,map方法需要一个函数型接口Functional,
        // sorted方法需要一个比较型接口Comparator,forEach方法需要一个消费型接口Consumer
        list.stream().filter(num -> num > 5)
                     .map(num1->num1*2)
                     .sorted((num1,num2)->num2-num1)
                     .limit(3)
                     .forEach(System.out::println);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值