lambda表达式简介:(本质是一个“语法糖”)
Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。
Lambda表达式语法:
基本语法:
(paramets)->expression
或:
(parameter)-> (statement)
匿名类型的最大问题就在于其冗余的语法。有人戏称匿名类型导致了“高度问题”。而java API中可以使用匿名类型把行为内联,对接口进行实现,不必专门定义一个类。
例如:
public interface ActionListener {
void actionPerformed(ActionEvent e);
}
这里并不需要专门定义一个类来实现 ActionListener,因为它只会在调用处被使用一次。用户一般会使用匿名类型把行为内联(inline):
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ui.dazzle(e.getModifiers());
}
});
匿名内部类的缺点:
- 语法过于冗余
- 匿名类中的this
- 类型载入和实例创建语义不够灵活
- 无法捕获非final的局部变量
- 无法对控制流进行抽象
lambda表达式是匿名方法, 它提供了轻量级的语法,从而解决了匿名内部内带来的“高度问题”。
Lambda表达式:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
第一个 lambda 表达式接收 x 和 y 这两个整形参数并返回它们的和;第二个 lambda 表达式不接收参数,返回整数 ‘42’;第三个 lambda 表达式接收一个字符串并把它打印到控制台,不返回值。
lambda表达式的语法由参数列表,箭头符号->和函数体组成。函数体即可以是一个表达式,也可以是一个语句块。
- 表达式:表达式会被执行,然后返回一个执行结果。
- 语句块:语句块中的语句会被执行,就先方法中的语句一样——
- return 语句会把控制权交给匿名方法的调用者
- break 和continue只能在循环体中使用
- 如果函数有返回值,name函数体内部的每一条路径都必须返回值。
表达式函数体适合小型 lambda 表达式,它消除了 return 关键字,使得语法更加简洁。
lambda 表达式也会经常出现在嵌套环境中,比如说作为方法的参数。为了使 lambda 表达式在这些场景下尽可能简洁,我们去除了不必要的分隔符。不过在某些情况下我们也可以把它分为多行,然后用括号包起来,就像其它普通表达式一样。
public class lambda_demo {
public void lambda0()
{
String []atp = {"Rafael Nadal", "Novak Djokovic",
"Stanislas Wawrinka",
"David Ferrer","Roger Federer",
"Andy Murray","Tomas Berdych",
"Juan Martin Del Potro"};
List<String> asList = Arrays.asList(atp);
//以前的循环方式
for(String s :asList)
{
System.out.println(s+" : ");
}
// 使用 lambda 表达式以及函数操作(functional operation)
asList.forEach((s) -> System.out.println(s + ":"));
// 在 Java 8 中使用双冒号操作符(double colon operator)
//asList.forEach(System.out::print);
asList.forEach(System.out::println);
}
public static void main(String []args)
{
lambda_demo demo = new lambda_demo();
demo.lambda0();
}
}
双冒号操作符(方法引用)
双冒号操作符详细介绍
形如ClassName::methodName 或者 ObjectName:: methodName 的表达式。为方法表达式。
方法引用的种类
方法引用有四种,分别是:
- 指向静态方法的引用
- 指向某个对象的实例方法的引用
- 指向某个类型的实例方法的引用
- 指向构造方法的引用
lambda语法代码非常的简洁。也可以用来实现Runnable接口。
//使用匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
}).start();
//1.2使用lambda表达式
Runnable racel = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
//1.3使用lambda表达式,更简洁方式
Runnable race2 = ()-> System.out.println("hello");
//这里直接调用lambda表达式。直接调用run方法,没开新线程。
racel.run();
race2.run();
下面列举lambda表达式一些例子:
//排序集合
String[] players = {"Rafael Nadal", "Novak Djokovic",
"Stanislas Wawrinka", "David Ferrer",
"Roger Federer", "Andy Murray",
"Tomas Berdych", "Juan Martin Del Potro",
"Richard Gasquet", "John Isner"};
// 1.1 使用匿名内部类根据 name 排序 players
Arrays.sort(players, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return (s1.compareTo(s2));
}
});
// 1.2 使用 lambda expression 排序 players
Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
Arrays.sort(players, sortByName);
// 1.3 也可以采用如下形式:
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
// 1.1 使用匿名内部类根据 surname 排序 players
Arrays.sort(players, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))));
}
});
// 1.2 使用 lambda expression 排序,根据 surname
Comparator<String> sortBySurname = (String s1, String s2) ->
( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );
Arrays.sort(players, sortBySurname);
// 1.3 或者这样,怀疑原作者是不是想错了,括号好多...
Arrays.sort(players, (String s1, String s2) ->
( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) )
);
// 2.1 使用匿名内部类根据 name lenght 排序 players
Arrays.sort(players, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return (s1.length() - s2.length());
}
});
// 2.2 使用 lambda expression 排序,根据 name lenght
Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());
Arrays.sort(players, sortByNameLenght);
// 2.3 or this
Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));
// 3.1 使用匿名内部类排序 players, 根据最后一个字母
Arrays.sort(players, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
}
});
// 3.2 使用 lambda expression 排序,根据最后一个字母
Comparator<String> sortByLastLetter =
(String s1, String s2) ->
(s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
Arrays.sort(players, sortByLastLetter);
// 3.3 or this
Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));