Java 8的新特性中,最著名的可能就是Lambda表达式了,基于此才能Java 8下面的函数式编程。虽然Lambda表达式说的很神奇,其实它并不能做任何新东西,只是能以比以前更简洁的方式来实现一些功能而已。Lambda的一个典型场景就是在处理不断变化的需求时,将函数做为方法的参数,这样满足不断变化的需求。
举例来说,比说我们做一个在线书籍查询应用,假设我们需要按照书名(模糊查询)、类别、价格区间进行查询,我们需要写这样一个查询方法,在Java 8之前,由于我们希望我们的方法可以适应未来需求的变化,如比将来可能增加按出版社查询,因此我们可以采用策略设计模式,每一种查询条件做成一种策略。
采用策略设计模式
首先定义一个查找条件接口,如下所求:
public interface BookFinder {
public boolean checkBook(BookVo bookVo);
}
表1
定义接口的好处是当查询条件增加时,我们只需要实现新增的查询条件,而无需修改之前的代码。
下面是对书名模糊查询的实现和调用,在这里,我们没有像通常的那样,定义一个类来实现BookFinder这个接口,因为我们想要尽量做到代码简洁,所以我们采用匿名类的方式来实现:
public void startup() {
List<BookVo> books = prepareBooks();
String name = "Java";
List<BookVo> result = findBooks(books, new BookFinder() {
@Override
public boolean checkBook(BookVo bookVo) {
if (bookVo.getBookName().indexOf(name) >= 0) {
return true;
}
return false;
}
});
for (BookVo book: result) {
System.out.println("##:" + book.getBookName() + ":" + book.getPrice() + "!");
}
}
表2
选择书籍具体的实现函数:
public List<BookVo> findBooks(List<BookVo> books, BookFinder finder) {
List<BookVo> result = new ArrayList<BookVo>();
for (BookVo book:books) {
if (finder.checkBook(book)) {
result.add(book);
}
}
return result;
}
表2.1
这样我们就比较完美地实现按书名模糊查询功能,但是在Java 8中,由于有了Lambda表达式,我们就有了更简洁的实现方式。
使用Lambda表达式,我们第一步也是定义一个函数式接口:
@FunctionalInterface
public interface FBookFinder<T> {
public boolean checkBook(T t);
}
表3
如上代码所示,我们声明的接口是函数式接口,其只能有一个公共抽象接口,由注解@FunctionalInterface来表示。另外,我们利用Generic机制,对方法的参数进行参数化,这样使这个接口不仅可以处理书籍,可以处理其他事务的查询。
下面是对函数接口的调用:
方式一:直接初始化函数式接口并作为方法调用的参数
public void testLambda() {
List<BookVo> books = prepareBooks();
List<BookVo> result = findBookByName(books, (BookVo bookVo) -> {if (bookVo.getBookName().indexOf("Java")>=0) {return true;} else {return false;}});
for (BookVo book: result) {
System.out.println("Lambda:" + book.getBookName() + ":" + book.getPrice() + "!");
}
}
表4
方式二:声明函数式接口变量,然后作为参数传入
public void testLambda() {
List<BookVo> books = prepareBooks();
String bookName = "Java";
FBookFinder<BookVo> fbf = (BookVo bookVo) -> {if (bookVo.getBookName().indexOf(bookName)>=0) {return true;} else {return false;}};
List<BookVo> result = findBookByName(books, fbf);
for (BookVo book: result) {
System.out.println("Lambda:" + book.getBookName() + ":" + book.getPrice() + "!");
}
}
表5
具体的函数实现如下所示:
public <T> List<T> findBookByName(List<T> books, FBookFinder<T> finder) {
List<T> result = new ArrayList<T>();
for (T book : books) {
if (finder.checkBook(book)) {
result.add(book);
}
}
return result;
}
表6
综上所述,Lambda表达式的引入,确实对程序适应不同的需求变化,提供了一种比之前更加简洁的实现方式,同时Java 8将函数提升到了与类机同的高度,可以做为参数进行传递,提供了更大的灵活性。