在这篇文章中,我想介绍一下Java 8最吸引人的新特性——lambda表达式。
先贴上lambda表达式的基本语法,有两种形式:java
lambda容许把函数做为一个方法的参数传递进方法中,体现了函数式编程思想。使用lambda表达式可使代码变得更加简洁紧凑。lambda表达式的本质只是一个所谓的“语法糖”,并无为Java语言添加新的功能,而是对已有功能进行了封装,由编译器推断并转换为常规的代码,所以能够用更少的代码来实现一样的功能。我我的以为,lambda表达式虽好,但不要乱用,用在合适的地方,能够有效减小代码量,使代码更加简洁,而滥用只会下降代码的可读性,使程序难以调试和维护。那么lambda表达式的应用场景是什么呢?
网上有不少lambda表达式的例子,我看了半天,以为无外乎就两个场景(我的浅显观点......):
一是代替函数式接口。函数式接口简单来讲就是只包含一个抽象方法的接口,好比Java标准库中的java.lang.Runnable和java.util.Comparator都是典型的函数式接口。对于函数式接口,除了可使用Java中标准的方法来建立实现对象以外,还可使用lambda表达式来建立实现对象,这能够在很大程度上简化代码的实现。在使用lambda表达式时,只须要提供形式参数和方法体。因为函数式接口只有一个抽象方法,因此经过lambda表达式声明的方法体确定是这个惟一的抽象方法的实现,并且形式参数的类型能够根据方法的类型声明进行自动推断(即形式参数能够省略类型)。
第二个场景,就是和集合配合使用。Java 8新增了两个对集合数据进行批量操做的包:java.util.function和java.util.stream。能够说,lambda表达式和stream是自Java语言添加泛型和注解以来最大的变化,lambda表达式很大程度上影响了咱们在处理集合时的编码方式。express
下面,我经过几个典型的例子带你们领略lambda表达式的强悍:编程
传统方式ide
public class runnableTest {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("I am Hawk.");
}
}).start();
}
}
复制代码
使用lambda表达式函数式编程
public class runnableTest {
public static void main(String[] args) {
new Thread(() ->
System.out.println("I am Hawk.")
).start();
}
}
复制代码
经过这个例子,咱们也能够进一步熟悉lambda表达式的声明方式:由形式参数和方法体两部分组成,中间经过“->”分隔。形式参数一般状况下不须要包含类型声明,能够进行自动推断。由于 System.out.println("I am Hawk.") 是单行语句,能够不用花括号“{}”括起来,若是方法体包含多行语句,则须要用“{}”括起来。函数
关于Comparator的机制,不在咱们此次的讨论范围内,我有时间...额...大概会写。总之,当咱们相比较的对象没有实现Comparable接口时,可使用Comparator接口并实现其中的compare方法进行比较。好比说,有这样一个Penple类:编码
// 使用lombok注解自动生成构造器与get、set方法等
@Data
@NoArgsConstructor
@AllArgsConstructor
public class People {
private String name;
private Integer age;
}
复制代码
如今我想按照年龄对People对象进行排序:
传统方式spa
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
Collections.sort(peopleList, new Comparator<People>() {
@Override
public int compare(People p1, People p2) {
return p1.getAge().compareTo(p2.getAge());
}
});
}
}
复制代码
使用lambda表达式调试
// 方法一
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
Collections.sort(peopleList, (p1, p2) ->
p1.getAge().compareTo(p2.getAge()));
}
}
// 方法二
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
peopleList.sort(Comparator.comparing(People::getAge));
}
}
复制代码
不知道你们咋想的,反正我当时知道还有方法二这种写法时是真的惊了。感受Java 8中的集合类型在增长了lambda表达式的支持以后变得......emmm高深莫测。须要注意一点,在方法二中,还使用了Java 8的另外一个新特性——方法引用,就是那两个冒号“::”(有点C++的赶脚)。方法引用能够在不调用某个方法的状况下引用一个方法,是另外一种实现函数式接口的方法,能够进一步简化代码。code
传统方法
public class foreachTest {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList("a", "b", "c"));
for (String str : stringList) {
System.out.println(str);
}
}
}
复制代码
使用lambda表达式
public class foreachTest {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList("a", "b", "c"));
stringList.forEach(System.out::println);
}
}
复制代码
额......先写到这里吧,由于stream部份内容较多,过几天再补充完。此次主要介绍了使用lambda表达式的第一个场景——代替函数式接口。这是一个趋势,但愿你们在从此的编码中,能逐渐抛弃匿名内部类,改用lambda这种更为简洁的写法。下次我将重点介绍lambda在集合中的使用以及如何与stream进行配合。