目录
一、概述
java8中一个非常重要的特性就是lambda表达式,我们可以把它看成是groovy的闭包概念。
它允许把函数当做参数来使用,是对面向函数式编程的思想的实现,使代码看起来更加简洁明了。
在java8之前大部分通过匿名内部类来实现。
二、语法
(parameters) -> expression;
2.1 没有入参:() -> expression;
//匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("running!");
}
}).start();
// lambda表达式
new Thread(() -> System.out.println("running!")).start();
2.2 一个入参:(param1) -> expression;
//常规写法
List<String> list = new ArrayList<>();
for (String s : new String[]{"english", "japan"}) {
if (s.contains("e")) {
list.add(s);
}
}
// lambda表达式
List<String> list = Stream.of("english", "japan").filter((value) -> value.contains("e")).collect(Collectors.toList());
2.3 多个参数: (Type1 param1,Type2 param2,Type3 param3) -> expression;
//常规写法
List<String> list = new ArrayList<>();
for (String s : new String[]{"english", "japan", "chinese"}) {
if (s.contains("e")) {
list.add(s);
}
}
// lambda表达式
List<String> asList = Stream.of("english", "japan", "chinese").filter((value) -> value.contains("e")).collect(ArrayList::new, ArrayList::add,
ArrayList::addAll);
2.4 有返回值:(Type parameters) -> return value;
//常规写法
StringBuilder sb = new StringBuilder();
List<String> list = Arrays.asList("english", "japan", "chinese");
for (int i = 0; i < list.size(); i++) {
if (i != 0) {
sb.append(",");
}
sb.append(list.get(i).toLowerCase(Locale.US));
}
return sb.toString();
// lambda表达式
String message = Stream.of("english", "japan", "chinese").map((value) -> value.toLowerCase(Locale.US)).collect(Collectors.joining(","));
2.5 主体多语句:(parameters) -> {
expression1;
expression2;
return value;
}
//常规写法
Map<String,String> map = new HashMap<>();
map.put("1","zhangsan");
map.put("2","lisi");
map.put("3","wangwu");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// lambda表达式
map.forEach((key,value) -> {
System.out.println(key);
System.out.println(value);
});
三、规则
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:
i) 一个参数,圆括号可省略;
ii) 多个参数,必须有圆括号;
可选的大括号:
i) 主体包含了一个语句,大括号可省略;
ii) 主体包含多个语句,必须有大括号;
可选的返回:
i) 返回是void类型,则不需要return;
ii) 主体只有一个表达式返回值,return可省略;
iii) 返回非void类型,主体有多个表达式,需显示return返回值;
四、方法引用
构造函数:
ClassName::new
static class Country {
private String name;
public Country(String name) {
}
public void say() {
System.out.println(name + " language");
}
}
//常规写法
for (String s : new String[]{"english", "japan", "chinese"}) {
new Country(s).say();
}
// lambda表达式
Stream.of("english", "japan", "chinese").map(Country::new).forEach(Country::say);
静态方法:
ClassName::staticMethod
//常规写法
List<Integer> list = new ArrayList<>();
for (String s : new String[]{"124", "123", "432"}) {
list.add(Integer.valueOf(s));
}
// lambda表达式
List<Integer> list = Stream.of("124", "123", "432").map(Integer::valueOf).collect(Collectors.toList());
对象方法:
ClassName::method
Stream.of("english", "japan", "chinese").map(Country::new).forEach(Country::say);
当前实例调用:
this::method
// lambda表达式
static class Student {
public void sayWord(String word) {
System.out.println(word.concat("friend"));
}
public void sayHello() {
Stream.of("hello", "thanks").forEach(this::sayWord);
}
}
五、变量作用域
5.1 lambda 表达式只能引用标记了 final 的外层局部变量
final int num = 1;
Function<Integer, String> s = (param) -> String.valueOf(param + num);
System.out.println(s.apply(2));
5.2 lambda 表达式不允许声明一个与局部变量同名的参数或者局部变量
//编译出错
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());
六、与匿名内部类的区别
6.1:this关键字解读不同
lambda表达式中的this为写此Lambda 的外部类,匿名类的关键词 this 解读为匿名类。
6.2:编译原理不同
java编译器编译 Lambda 表达式并将他们转化为类里面的私有函数,
它使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法,匿名类会编译为一个class文件