zoukankan      html  css  js  c++  java
  • jdk8新特性学习总结

    jdk8新增了一下几个新的特性

    • lambda表达式和函数式接口
    • 方法引用
    • stream流

    这里stream流的api比较多在这篇文章就不详细展开了。

    lambda表达式和函数式接口

    lambda表达式

    先简单介绍 一下lambda表达式:lambda表达式也可以称为是闭包,它允许把函数作为一个方法的参数传入到方法中,使用lambda表达式可以使代码更简介美观。

    语法

    我们来看下它的语法格式,很简单清晰

    (入参)->{返回值}
    

    他有如下几个特性

    • 可选类型声明:入参部分传参的时候可以不声明参数类型,编译器能直接统一识别参数类型。
    • 可选参数圆括号:入参部分是一个参数,那么可以把圆括号省略,如果是多个参数圆括号不能省略。
    • 可选大括号:如果打括号里只有一句代码就可以省略大括号。
    • 可选返回关键字:如果大括号内只有一个需要返回的值或则表达式,那么就可以省略return返回关键字。

    使用

    常见的几种写法

    //无参不带括号且不带返回关键字
    ()->1;
    //带返回关键字
    ()->return 1;
    //带大括号
    ()->{return 1};
    //有一个参数带小括号
    (int a)->return a+1;
    //不带小括号(不建议这么写)
    a ->return a+1;
    //多个参数,不写参数类型
    (a,b)->{a+b};
    //有参打印一句话
    (String a)->System.out.printl(a)
    

    大致的写法就是这样,后面会有更详细的用法。
    lambda表达式常常和函数式接口一起使用,那么我们就来了解一下函数式接口

    函数式接口

    函数式接口首先它是个接口,然后这个接口里面有且仅有一个抽象方法,然后在该接口上加一个@FunctionalInterface注解,那么它就是一个函数式接口了。

    语法

    @FunctionalInterface
    public interface FunctionIntfaceDemo {
        String test1();
    }
    

    这样就简单定义了一个函数式接口。

    如何使用

    其实函数式接口可以隐式转换为lambda表达式
    像上面我们定义的那个函数式接口它就可以用lambda表达式这么写

    ()->"返回一个String类型的参数";
    

    或者直接赋值

    FunctionIntfaceDemo test = ()->"返回一个String类型的参数";
    

    java 给我们提前定义好了4个常用的函数式接口
    分别是Functio< R, T>,Consumer,Supplier,Predicate。
    接下来慢慢解释着几个函数的作用。
    这里我们只简单的了解不做深入的讨论

    Function< R,T >

    这个函数它接收一个R对象类型的值,然后返回一个T对象类型的值,然后通过调用apply方法去执行内容。
    我们直接看用法,这里我为了方便大家观察就不去简写lamdba表达式了

    Function<Integer,Integer> s =(Integer a)->{return a+2;};
    Integer apply = s.apply(2);
    

    这里接收的参数必须是对象类型,不能是基础类型。
    这串代码接收了一个integer类型的a,然后返回了一个integer类型的a+2。接着调用了apply传入了一个2,获得了一个结果。

    关于Function的细节部分就不展开了,不然这篇文章就长了

    Consumer

    Consumer是消費者的意思,Consumer< V>就是接收一个V对象的值,然后不返回,本质上就接收的这个对象被消费掉了。然后使用accept去执行。

    Consumer<Integer> consumer = (a)-> System.out.println(a) ;
    consumer.accept(5);
    

    Supplier

    Supplier是提供者的意思,和上面的消費者相反,它不接收参数,Supplier< T>返回一个T对象类型的值。通过调用get方法执行。

    Supplier<String> supplier = () -> "提供产品";
    String s1 = supplier.get();
    

    Predicate

    这个单词翻译过来是谓语的意思,它是一个谓语接口Predicate< T,Boolean>它接收一个T类型的对象然后返回一个布尔值,通过test方法执行。其实它和Function一样,但是为了区分开来所以单独划分了出来。

    Predicate<Integer> predicate = (Integer a) -> a >= 10;
    boolean test1 = predicate.test(15);
    

    其它接口

    其实Java给我们提供了40多种函数接口,前面介绍的是最基础的四种接口。剩下的几个接口都是上面几个接口的变式,大多数都是对参数类型和参数数量做了限制。这里我们分别举一个例子

    参数类型限制的接口:IntToDoubleFunction,接受一个int类型输入,返回一个double类型结果。这里同时限制了入参和返回值。这个就是Function的变种。

    返回值类型限制的接口:DoubleSupplier,代表一个double值结构的提供方,其实它就是Supplier的变种

    数量限制接口:这类接口需要接收两个参数,此类接口的名字前面一般都是Bi开头Binary(二元的意思),比如BiConsumer< T,U>,代表了一个接受两个输入参数的操作,并且不返回任何结果。

    Operator接口:这类接口就是一种简写一般用于两个相同类型的计算,这类型的接口总共就两种(不是两个),分别是一元操作的UnaryOperator< T>,接受一个参数为类型T,返回值类型也为T。和BinaryOperator,代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果。

    方法引用

    方法引用我们可以理解为lambda表达式的另外一种形式具体概念就不多说了。

    方法引用主要有四类,分别是静态方法引用实例方法引用对象方法引用以及构造方法引用

    接下来我们一个一个看他们的使用方法

    我们先看下他们对应的语法格式

    //静态方法引用
    类名::静态方法
    //实例方法引用
    对象实例名::实例方法
    //对象方法引用
    对象名::实例方法
    //构造方法引用
    类名::new
    

    上面这样提现出来可能不是太清晰,我们来具体看一下代码

    代码举例

    这里是列举了上面的语法结构,其实在使用时候可以很灵活。

    public class MethodReferenceDemo {
    
        static void StaticMethodQuote(){
            System.out.println("静态方法引用");
        }
    
        void InstanceMethodQuote(){
            System.out.println("实例方法引用");
        }
    
        MethodReferenceDemo(){
            System.out.println("构造方法的引用");
        }
        public static void main(String[] args) {
            //静态方法引用
            Runnable staticMethodQuote = MethodReferenceDemo::StaticMethodQuote;
            staticMethodQuote.run();
            //实例方法引用
            MethodReferenceDemo methodReferenceDemo = new MethodReferenceDemo();
            Runnable instanceMethodQuote = methodReferenceDemo::InstanceMethodQuote;
            instanceMethodQuote.run();
            //对象方法引用
            Consumer<MethodReferenceDemo> objectMethodQuote = MethodReferenceDemo::InstanceMethodQuote;
            objectMethodQuote.accept(new MethodReferenceDemo());
            //构造方法的引用
            Runnable aNew = MethodReferenceDemo::new;
            aNew.run();
        }
    }
    
    

    我们来看下打印结果

    静态方法引用
    构造方法的引用
    实例方法引用
    构造方法的引用
    对象方法的引用
    构造方法的引用
    

    这里构造方法的引用打印了三次是因为,我们将对象实例化了三次,除了静态方法的引用其余的都调用了构造方法。

    其实上面的方法引用是可以直接转成lambda表达式的
    大致就是这个样子

    //静态方法引用
    Runnable staticMethodQuoteLambda = () -> MethodReferenceDemo.StaticMethodQuote();
    //实例方法引用
    Runnable instanceMethodQuoteLambda = () -> methodReferenceDemo.InstanceMethodQuote();
    //对象方法引用
    Consumer<MethodReferenceDemo> objectMethodQuoteLambda= (objectMethodQuoteParameter)->objectMethodQuoteParameter.ObjectMethodQuote();
    objectMethodQuoteLambda.accept(new MethodReferenceDemo());
    //构造方法引用
    Runnable ConstructionMethodLam = () -> new MethodReferenceDemo();
    

    总结一下大概是这样的

    //静态方法引用
    (参数)->类名.静态方法(参数)
    //实例方法引用
    (参数)->实例名.实例方法(参数)
    //对象方法引用
    (对象,参数)->类名.实例方法(参数)
    //构造方法引用
    (参数)->new 类名(参数)
    

    所以本质上这些东西区别也特别大

    关于stream后面有时间就在专门写一篇总结下。

  • 相关阅读:
    matplotlib数据可视化之柱形图
    xpath排坑记
    Leetcode 100. 相同的树
    Leetcode 173. 二叉搜索树迭代器
    Leetcode 199. 二叉树的右视图
    Leetcode 102. 二叉树的层次遍历
    Leetcode 96. 不同的二叉搜索树
    Leetcode 700. 二叉搜索树中的搜索
    Leetcode 2. Add Two Numbers
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/ccsert/p/12844463.html
Copyright © 2011-2022 走看看