3

Lambda表达式是java8的新特性,没用过的人可能会对它比较抵触,用过的人呢又为之痴迷。在Lambda表达式中,有个很重要的用法是简化某些匿名类,我们通过下面的例子来感受一下。

有个老婆婆有一只鸡每天都要生蛋,她每天都要给鸡蛋记上生产日期

无参无返回值

1.7及之前的写法如下:
定义一个标记鸡蛋的接口MarkEgg:

public interface MarkEgg {  
    void mark();  
}

然后用匿名类调用,记录10天老婆婆的动作。

public class OldLady {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            mark(new MarkEgg() {
                @Override
                public void mark() {
                    System.out.println("今天的鸡蛋");
                }
            });
        }
    }

    public static void mark(MarkEgg markEgg) {
        markEgg.mark();
    }
}

我们可以看到,虽然匿名类省略了类名,但是还是不够简洁的。我们看看用Lambda是怎么简化代码的。

public class OldLady {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            mark(() -> System.out.println("今天的鸡蛋"));
        }
    }

    public static void mark(MarkEgg markEgg) {
        markEgg.mark();
    }
}

另外,在MarkEgg接口上,要标记@FunctionalInterface,这个注解表示,这个接口是函数式接口,如果我们标记了@FunctionalInterface,但它却不是函数式接口,编译器就会报错,但是不写也是可以的,如同@Override

@FunctionalInterface  
public interface MarkEgg {  
    void mark();  
}

下面对比一下两个主体部分:
image.png
Lambda表达式有三个部分:
第一个是参数列表,对应图中的1,这里例子没有参数。
第二个是->,把参数和Lambda主体分开。
第三个是Lambda主体,对应上面的输出语句2

无参有返回值

老婆婆并不会写字,所以她让别人代写,只需要跟别人说在鸡蛋写什么

MarkEgg接口简单的改一下:

@FunctionalInterface  
public interface MarkEgg {  
    String mark();  
}

OldLady类:

public class OldLady {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            mark(() -> "今天的鸡蛋");
        }
    }

    public static void mark(MarkEgg markEgg) {
        System.out.println(markEgg.mark());
    }
}

注意一下,Lambda主体中,并没有return。

有参有返回值

此时,别人跟老婆婆说,你每次都写今天,你以后怎么知道是哪天的,所以你要告诉我是哪天。

MarkEgg接口加上参数:

@FunctionalInterface  
public interface MarkEgg {  
    String mark(int day);  
}

OldLady类:

public class OldLady {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            mark((int day) -> String.format("第%s天的鸡蛋", day), i + 1);
        }
        for (int i = 0; i < 10; i++) {
            mark(day -> String.format("第%s天的鸡蛋", day), i + 1);
        }
    }

    public static void mark(MarkEgg markEgg, int day) {
        System.out.println(markEgg.mark(day));
    }
}

我们上面参数,有两个形式,第一个是(int day),第二个直接是day,把参数类型去掉。

总结

Lambda的基本语法是

(parameters) -> expression

或(我们上面都是单行的,如果是多行,就要加大括号,且如果是有返回值要加return

(parameters) -> { statements; }

大军
847 声望183 粉丝

学而不思则罔,思而不学则殆