平时项目中用到lambda表达式都是些常规操作,没有仔细研究过语法规则,今天面试还有被问到。现在总结一下用法,希望以后能够运用更加熟练~~
lambda表达式作用?
lambda表达式是匿名内部类的另一种写法,直接作用就是为了简化代码,方便阅读
如何使用lambda表达式?
/**
* 此注解只是为了声明此接口为函数式接口,并不影响lambda的使用。
* 函数式接口只能有一个抽象方法,添加该注解后如果存在其他抽象方法,
* 则会编译报错有提示信息。但如果没加的话,只要满足只有一个抽象方法的接口
* 也可以使用lambda表达式,不影响使用。
*/
@FunctionalInterface
interface LambdaInterface{
void learnLambda(String str);
}
@FunctionalInterface 不加不影响使用,示例代码如下:
public class StreamTest{
public static void main(String[] args) {
String str = "哈哈哈 lambda!";
LambdaTest2 lambdaTest2 = (String aa) -> System.out.println(aa);
// LambdaTest2 lambdaTest2 = System.out::println; 可以使用方法引用替代
lambdaTest2.show(str);
}
public interface LambdaTest2{
void show(String name);
}
}
执行结果:
但是如果需要声明为函数接口最好还是加上@FunctionalInterface,防止该接口被随意篡改!!!
写法精简规则
- 参数的数据类型可以省略,多参数时,省略时需全部省略方可
- 参数的小括号,当只有一个参数时,可以省略小括号
- 方法体的大括号,方法体中只有一句代码的时候,可以省略大括号
- 如果方法体中唯一的语句为返回语句,则省略大括号同时需要再省略return
其实如果查看集合遍历的foreach源码就会看到
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
// ArrayList.forEach()
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
平时写的遍历操作,就相当于传入了一个匿名对象,此匿名对象就是用lambda来表示的。foreach方法通过传入的匿名对象,for循环遍历调用匿名对象的唯一的实现方法,来完成遍历操作。