从下面的例子入手
类Clazz
:
class Clazz {
private Integer x;
public Clazz(Integer x) {
this.x = x;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
@Override
public String toString() {
return x + ", ";
}
}
现在有一个Clazz
的List
,要对其进行排序,有以下几种方法:
==需要强调一点,下面的代码使用到了list.sort()
,在jdk1.8
中接口可以有默认方法,也就是在List
接口中sort
方法已经有了默认实现。 在jdk1.8之前,对List
排序,可以使用Collections
帮助==
1) 实现Comparator
接口,但是没有必要,因为可能只使用了一次这个类。
2) 使用匿名类:
public static void main(String[] args) {
List<Clazz> list = new ArrayList<>(
Arrays.asList(new Clazz(10), new Clazz(80), new Clazz(50), new Clazz(30)));
list.sort(new Comparator<Clazz>() {
@Override
public int compare(Clazz o1, Clazz o2) {
return o1.getX().compareTo(o2.getX());
}
});
}
使用匿名类,可以不必创建类,如果现在要反向排序,又要实例一个匿名类。 这时会发现有许多一样的代码,如下面的这部分:
new Comparator<Clazz>() {
@Override
public int compare(Clazz o1, Clazz o2) {
}
}
不管正序还是逆序排,都会写这段代码,然而真正用到的只是return o1.getX().compareTo(o2.getX());
这部分的内容。
3) 使用Lambda
表达式
public static void main(String[] args) {
List<Clazz> list = new ArrayList<>(
Arrays.asList(new Clazz(10), new Clazz(80), new Clazz(50), new Clazz(30)));
list.sort((Clazz a1, Clazz a2) -> a1.getX().compareTo(a2.getX()));
}
非常简短,(Clazz a1, Clazz a2) -> a1.getX().compareTo(a2.getX())
这一句话代替了上面繁杂的创建匿名类等过程。接下来就会讲解Lambda
表达式。
Lambda表达式
表达式语法
使用匿名类时,有许多模板代码,并且比较啰嗦。 使用Lambda
表达式可以简洁的表示一个行为或传递代码。
分析(Clazz a1, Clazz a2) -> a1.getX().compareTo(a2.getX())
(Clazz a1, Clazz a2)
参数列表,这是Lambda
参数- 然后有一个
->
,把参数列表和Lambda
主体分离 - 后面部分为
Lambda
主体,比较2个Clazz
的大小,表达式就是Lambda
返回值。
一些合法的Lambda
表达式:
1. () -> {}
,该表达式没有参数,并返回void
。类似于public void XXX(){}
2. () -> "Hello"
, 表达式没有参数,且返回String
类型Hello
3. () -> { return "Hello"; }
, 表达式没有参数,返回Hello
,这里使用了显示返回语句return
,所以需要使用花括号
4. (Integer i) -> { return "Hello" + i; }
,参数为Integer
类型,返回String
在哪里使用Lambda
可以在函数式接口使用,函数式接口就是只定义了一个抽象方法的接口。之所以上面的排序的Lambda
表达式能够被sort
接受,因为Comparator
就是一个函数式接口。Runnable
也是一个函数式接口,举个例子:
静态方法process
,参数为一个Runnable
public static void process(Runnable r) {
r.run();
}
分别使用匿名函数和Lambda
表达式:
//匿名类
process(new Runnable() {
@Override
public void run() {
System.out.println("Hello World");
}
});
//Lambda表达式
process(() -> System.out.println("Hello World"));
() -> System.out.println("Hello World")
可以传给Runnable
接口,如何判断传给的表达式是否正确?
函数式接口的抽象方法的签名基本上就是Lambda
的签名,这个抽象方法叫做函数描述符。 Runnable
接口没有参数也没有返回值,() -> System.out.println("Hello World")
表达式也不接受参数,且返回的为void
,所以该表达式的签名和Runnable
接口的run()
方法签名是一样的。也就是说对于同一个函数式接口,可以使用不同的Lambda
表达式。
Java8
中添加了很多函数式接口,这里不在给出,在java.util.function
包下。
本文记录了一些自己学习到的知识,并没有很全面的讲解,本人水平有限~。