JDK8 - Lambda表达式(二)
本篇主要介绍Lambda的使用以及方法引用 A::B 以及JDK主自带的:Function (构造型函数接口)、Consumer (消费型函数接口)、Predicate(判断型函数接口)、Supplier(供给型函数接口)
方法引用
方法引用分为普通方法引用和静态方法引用,普通方法引用为:对象名::方法,静态方法引用为:类::方法。它用在函数式接口的唯一抽象方法实现中。
定义一个普通的方法:
public class RandomNumImpl {
/**
* 产生一个随机数
*/
public void buildNum() {
Random random = new Random();
System.out.println(random.nextInt(10));
}
}
定义一个函数式接口Glue
@FunctionalInterface
public interface Glue {
void print();
}
如果用Lamabe来表示一个函数式接口Glue的匿名实现类,并且print方法的实现还需要用到RandomNumImpl类,常用的写法是:
@Test
public void test2() {
RandomNumImpl randomNum = new RandomNumImpl();
Glue glue = () -> {
randomNum.buildNum();
};
glue.print();
}
也可以简化成:
@Test
public void test3() {
RandomNumImpl randomNum = new RandomNumImpl();
Glue glue = randomNum::buildNum;
glue.print();
}
如果把函数式接口Glue的唯一抽象方法print的实现改成需要调一个类的静态方法,还可以简化成:
public class RandomNumImpl {
public static void buildLongNum() {
Random random = new Random();
System.out.println(random.nextLong());
}
}
@Test
public void test4() {
Glue glue = RandomNumImpl::buildLongNum;
glue.print();
}
*** 小结一下: A::B A表示Lamada将要实现的抽象方法所需外部变量名,B表示A的某个方法,如果是静态方法,A则为了类名。***
下面实战应用一下 A::B的写法。下面例子用到的Book类如下:
@Data
public class Book {
private String name;
private Double price;
public Book() {
}
public Book(String argName) {
this.name = argName;
}
public Book(String argName, Double argPrice) {
this.name = argName;
this.price = argPrice;
}
public void addPrice(Double argPrice){
this.price = price + argPrice;
}
public static void goPage(Integer page) {
System.out.println("goto page = " + page);
}
public boolean compare(Double argPrice){
return this.price > argPrice;
}
}
Function 构造型函数接口
作用:接收一个参数,返回一个对象。Function的源码:
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
以Book为例构造一个Function的Lambda表达式
@Test
public void testFunction1() {
Function<String, Book> function = (name) -> {
return new Book(name);
};
Book book = function.apply("JAVA");
log.info(book.toString());
}
JDK提供了一个新的写法:类::new 来简化上面的写法:
@Test
public void testFunction2() {
Function<String, Book> function = Book::new;
Book book = function.apply("JAVA");
log.info(book.toString());
}
使用 类::new 表示直接由类的构方法来实现Function接口中的apply方法,这个里有一个特殊之在于apply方法有一个参数,因此类必须要要有一个参数的构造方法
Consumer 消费型函数接口
作用:接收一个对象,自由完成对对象的使用。源码:
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
由类的普通方法构造一个Consumer的Lambda表达式
@Test
public void testConsumer1() {
Consumer<Book> consumer = (argBook) -> {
argBook.addPrice(10D);
};
Book book = new Book("Java", 60D);
consumer.accept(book);
log.info(book.toString());
}
也可以使用 变量名A::普通方法名B 来实现Consumer,即为:Consumer的accept方法由变量A的方法B实现,要求A的B方法是:有参并无返回值
@Test
public void testConsumer2() {
Book book = new Book("Java", 60D);
Consumer<Double> consumer = book::addPrice;
consumer.accept(10D);
log.info(book.toString());
}
由类的静态方法构造一个Consumer的Lambda表达式
@Test
public void testConsumer3() {
Consumer<Integer> consumer = (page) -> {
Book.goPage(page);
};
consumer.accept(100);
}
使用 类名A::静态方法名B 来实现Consumer,即为:Consumer的accept方法由类名A的方法B实现。要求与普通方法一样,有参并无返回值
@Test
public void testConsumer4() {
Consumer<Integer> consumer = Book::goPage;
consumer.accept(200);
}
传说中的:System.out::println
@Test
public void testConsumer5() {
Consumer<String> consumer = System.out::println;
consumer.accept("Hello Word");
}
上面等于:
@Test
public void testConsumer6(){
new Consumer(){
@Override
public void accept(Object o) {
System.out.println(o);
}
}.accept("Hello Word");
}
即用System.out类的println实现了Consumer接口的accept方法。
Predicate和Supplier其实就是对Consumer增强,有接收参数和返回值页
构造一个Predicate的Lambda表达式
Predicate
作用:接收一个参数,返回一个boolean值。用于各类判断。源码:
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
构造一个Predicate的Lambda表达式
@Test
public void testPredicate1() {
Predicate<Book> predicate = (argBook) -> {
return argBook.getPrice() > 100;
};
Book book = new Book();
book.setPrice(120.0);
boolean bool = predicate.test(book);
log.info("bool={}", bool);
}
argBook.getPrice() > 100 是一个自由的实现,如果Book类用一个方法也是接收一个参数并且返回boolean,就可以用 ::
使用 变量名A::方法名B 来实现Predicate,即为:Predicate的test方法由变量A的方法B实现,要求A的B方法是:有参并有返回boolean
@Test
public void testPredicate2() {
Book book = new Book();
book.setPrice(120.0);
Predicate<Double> predicate = book::compare;
boolean bool = predicate.test(100D);
log.info("bool={}", bool);
}
Supplier
作用:无参,返回一个值。源码:
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
构造一个Supplier的Lambda表达式
@Test
public void testSupplier1() {
Book book = new Book();
book.setName("Spring");
Supplier<String> supplier = () -> {
return book.getName();
};
System.out.println(supplier.get());
}
使用 变量名A::方法名B 来实现Supplier,即为:Supplier的get方法由变量A的方法B实现。要求A的B方法是:无参并有返回值
@Test
public void testSupplier2() {
Book book = new Book();
book.setName("Spring");
Supplier<String> supplier = book::getName;
System.out.println(supplier.get());
}