Java lambda表达式

Posted Sakura

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java lambda表达式相关的知识,希望对你有一定的参考价值。

lambda表达式是一个匿名函数,通俗解释是:可以传递的、在以后执行一次或多次的代码块。Java8中引入的特性。

lambda表达式的语法

形式:(参数)-> 表达式

0.若表达式复杂,可以用大括号括起。{语句块}

1.没有参数的情况:仍然需要提供空括号。

()->{for (int i = 100;i >= 0;i--) System.out.println(i);}

2.如果可以推导出参数类型:可以忽略参数类型。

Compertor<String> comp = (first,second) ->first.length()-scond.length();//参数类型必为字符串

3.如果只有一个参数,可以推导出参数类型:可以省略小括号。

4.无需指定lambda表达式的返回类型,自动由上下文推导得出。

函数式接口

对于只有一个抽象方法的接口,需要这种接口的对象时,可以提供一个lambda表达式。只有一个抽象方法的接口被称为函数式接口。

如Array.sort方法需要提供一个数组和比较器(comparator)。比较器是实现了Comparator接口的实例对象。该接口只有一个方法。如普通实现:

class LengthComparater implements Comparator<String>{
    public int compare(String first,String second){
        return first.length() - second.length();
    }
}

这样,就可以创建一个LengthComparater类传入Array.sort函数中。

Array.sort(words,new LengthComparator())

而用lambda表达式:

Array.sort(words,(first,second)->first.length()-secong.length())

这样做,对compare方法的调用会执行这个lambda表达式的体,它把lambda看做一个函数。这样做法效率要高;代码可读性也要好一些。

方法引用

使用双冒号(::)分隔方法和对象名来表示一个方法引用,与lambda表达式效果相同。有3种写法:

object::instanceMethod(x,x,x...)   等价于(x,x,x...)->object.instanceMethod(x,x,x...)

Class::staticMethod(x,x,x,....)          等价于(x,x,x...)->object.staticMethod(x,x,x...)

Class::instanceMethod(x,y,z...)      等价于(x)->x.instanceMethod(y,z.....)  //第一个参数会成为方法的目标

可以在方法引用中使用this和super参数

构造器引用

与方法引用类似,方法名为new。例如Person::new是Person构造器的一个引用。

变量作用域

lambda表达式可以捕获外围作用域中变量的值,但却有些限制。

规则:lambda表达式中捕获的变量必须实际上是最终变量。

一个例子:

    public static void repeat(String text, int count){
        for (int i = 1;i <= count; i++){
            ActionListener ls = event ->{
                System.out.println(i + " " + text);
            };
            new Timer(10000,ls).start();
        }
    }

如上,对于text的打印是合法的,对i的打印却是非法的。text总是指向同一个对象;而i的值却会改变。

规则:lambda表达式的体与嵌套块有相同的作用域。

一个例子:

    Path first = Paths.get("usr/bin");
    Comparator<String> comb = (first,second) -> first.length()-second.length();

以上是非法的。方法中不能有两个同名的局部变量。所以以上lambda表达式不能使用first变量名作为参数。

处理lambda表达式

简单例子:重复一个动作n次,用到repeat方法。

repeat(10,()->(System.out.println("hello world"));

需要实现一个函数式接口,这里使用Runnable接口,调用action.run()时会执行这个函数主体:

public static void repeat(int n,Runnable action){
    for(int i;i<n;i++) action.run();
}

实际上lambda表达式能做的也就是转换成函数式接口。

一些常用的函数式接口:Runnable,Supplier,Consumer,BiConsumer,Function,BiFunction,UnaryOperator,BinaryOperator,Predicate,BiPredicate。

 

以上是关于Java lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章

Java的Lambda表达式

函数式编程

Java Lambda表达

聊聊Java 8的Lambda表达式和函数式接口

Java Lambda

Java 8 新特性总结