JDK8新特性学习(一) Lambda表达式和函数式接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Armour__r/article/details/79196717

Lambda表达式和函数式接口

刚进公司时,公司正处于由JDK7换用JDK8的时间短,之所以更换JDK版本,听说是公司业务中需要用到JDK8的一些新特性。鉴于我现在也无事可做,姑且来学习总结一下JDK8的一些特性吧。水平有限,这篇勉强算是对他人博客上零散内容的一个总结。

1. Lambda表达式

Lambda表达式 匿名函数,当需要一个函数而又不想给他一个命名时,在java中,对于那些只使用一次的方法使用这种方式,能够减少命名上的负担。

允许将行为传入函数,取代匿名类。很经典的就是一个实现Runnable接口的例子,之前很长一段时间用的是匿名内部类,现在有了lambda表达式来使用。

//使用匿名内部类
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("The old runable now is using!");
    }
}).start();

//使用lambda表达式
new Thread(() -> System.out.println("It's a lambda function!")).start();

减少了很多代码量,也使得代码结构更加清晰。

允许使用函数式风格编程,将函数当成参数传递给某个方法,或者把代码本身当作数据处理

结构写法上,lambda表达式由三部分组成: (参数列表),符号 -> ,函数体(多个语句时加上{})。可以访问类的成员变量和局部变量,但是会转为final。

具体的一些匿名函数的使用,由于不太能用到所以不过多说明,仅举部分例子来作为使用时写法的参考,以集合类的遍历为例,虽然用之前的写法也不复杂。之所以选择集合类就是因为很熟悉,不用写原先的遍历方法出来,也能很好的对比两种写法的差异。

//List的遍历
List<String> list = new ArrayList<>();
list.add("aaa");
...
... 
list.forEach(x -> System.out.println(x));

//Map的遍历
LinkedHashMap<Integer,Integer> lhm = new LinkedHashMap<>();
lhm.put(1, 4);
...
...
lhm.forEach((k,v) -> System.out.println("key:" + k + " value:" + v));

2. 函数式接口

函数式接口是SAM(Single Abstract Method )类型的接口,是为了让现有功能能和Lambda表达式能够良好兼容所想出的方法。

定义了这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个lambda表达式作为参数。换个角度说就是,当我们调用一个方法,可以传入lambda表达式作为参数,那么这个方法的参数类型,必定是一个函数式的接口。

就是指只有一个函数的接口,这样的接口可以被隐式转换为Lambda表达式。例如,java.lang.Runnablejava.util.concurrent.Callable等。

但是函数接口代码层面十分脆弱,只要这个接口中有其他的函数就会编译失败,为了解决函数接口在实际使用过程中的脆弱性。采用显式说明的方式,jdk8提供了一个@FunctionalInterface这个注解来进行声明。

不过默认方法和静态方法不会破环函数式接口的定义。

举上面提到的两个jdk中代码的例子:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

上面两个都是函数式接口的写法,然后我们来对比一下使用lambda和不使用lambda表达式的写法差别:

//不使用Lambda表达式时
Runnable runnable1=new Runnable(){
    @Override
    public void run(){
        System.out.println("RunningwithoutLambda");
    }
};

//使用Lambda表达式的写法
Runnable runnable2=()->{
    System.out.println("RunningfromLambda");
};

3. 其他

其他什么predicate,stream之类的以后有机会有时间再来补充讨论。

猜你喜欢

转载自blog.csdn.net/Armour__r/article/details/79196717