什么是lambda表达式
lambda 表达式是一个匿名函数
简化匿名内部类的调用
lambda表达式规范
- 接口中只有一个抽象方法
- 函数接口中定义Object类中的方法
- 使用默认或静态方法
- @FunctionalInterface 表示该接口为函数式接口
- ()->{}
package jdk8.lambda;
@FunctionalInterface
public interface Closeable {
void close();
// 允许存在Object类中的方法
String toString();
}
package jdk8.lambda;
public interface Callable {
void call();
}
package jdk8.lambda;
public class Main {
public static void main(String[] args) {
// 匿名内部类写法
Callable callable = new Callable() {
@Override
public void call() {
System.out.println("call");
}
};
callable.call();
// lambda表达式写法
// ((InterFace)()->{}).method()
((Callable) () -> System.out.println("hello,world")).call();
// 匿名内部类的方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
// lambda表达式方式
new Thread(()->{
System.out.println(Thread.currentThread().getName());
}).start();
// 函数式编程接口
((Closeable)()->System.out.print("close")).close();
}
}
lambda表达式写法
- (): 参数列表
- ->: 分隔符
- {}: 方法体
- 函数参数列表 不需要写类型 只需要写参数名称
// 无参lambda表达式
()->{
// doSomething
}
// 带参lambda表达式
(a,b)->{
// dSomething
}
不带参数的lambda表达式
// 不带参数的lambda表达式
new Thread(()->System.out.println("thread running...")).start();
thread running...
带参数的lambda表达式
package jdk8.lambda;
@FunctionalInterface
public interface Animal {
void bark(String tag);
}
// 带参数的lambda
((Animal) tag -> System.out.println(tag + ":wof ~")).bark("petter");
petter:wof ~
lambda表达式精简方案
方案1
((InterFaceName)(paramList)->).method();
- InterFaceName: 接口名称
- paramList: 参数列表
- methodBody: 方法体
- method: 要调用的方法
// lambda表达式精简
Animal animal = (tag) -> {
System.out.println(tag);
};
animal.bark("petter");
// 方案1
// ((InterFaceName)(paramList)->{methodBody}).method();
((Animal)(tag)->{
System.out.println(tag);
}).bark("petter");
/**
* - InterfaceName: 函数接口名称
* - paramList: 参数列表
* - methodBody: 方法体
*/
方案2
如果方法体内只有一行语句则不需要
{}
,并且也不需要写return
语句
// 方案2 如果方法体内只有一行语句则 可以去掉括号
((Animal) (tag) -> {
System.out.println(tag);
}).bark("petter");
((Animal) (tag) ->System.out.println(tag)).bark("petter");
方案3
方法引入
lambda表达式实战
forEach
ArrayList forEach 遍历
ArrayList<String> strings = new ArrayList<>();
strings.add("tom");
strings.add("jerry");
strings.add("wangcai");
// 传统遍历方案 匿名内部类
strings.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
// 但是通过分析 我们发现 他是一个 函数式接口 Consumer
// 既然它满足 函数式接口规范 那么他必然可以使用 lambda表达式
strings.forEach(s-> System.out.println(s));
集合排序
// 集合排序
ArrayList<Integer> integers = new ArrayList<>();
integers.add(99);
integers.add(5);
integers.add(7);
integers.add(180);
integers.add(130);
// 传统解决方案 Comparator 接口 匿名内部类
// 同样得知 是一个 函数式接口
integers.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
// 改进
integers.sort((o1,o2)->o1-o2);
integers.forEach(s-> System.out.println(s));
总结
- lambda表达式是为了简化匿名内部类
- lambda表达式的使用一定要满足
函数式接口
- 语法:()->{}
- 如果方法体内只有一行语句可以省略括号和return
- lambda表达式的出现极大地简化了代码