学习到匿名类以后,小王感觉到Java的浩瀚,然后继续学习,后来接触到Lambda,于是对待做了以下改造:
List<Student> list = filterStudent(students, student -> student.getAge() > 15);Lambda知识整理 Lambda定义
从上面的演进过程,我们基本上可以得到Lambda表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。Java中的Lambda表达式通常使用(argument) -> (body)语法书写,常用的Lamda表达式例子有:
(int a, int b) -> { return a + b; }() -> System.out.println("Hello World");
(String s) -> { System.out.println(s); }
函数式接口
函数式接口指的是是只包含一个抽象方法声明的接口。例如java.lang.Runnable就是一种函数式接口,在 Runnable接口中只声明了一个抽象方法方法void run();
@FunctionalInterfacepublic interface Runnable {
public abstract void run();
}
对于注解@FunctionalInterface对于lamda表达式来说的话并不是必要的,@FunctionalInterface是Java8新加入的一种接口,用于指明该接口类型声明是根据Java语言规范定义的函数式接口。Java8还声明了一些Lambda表达式可以使用的函数式接口,当你注释的接口不是有效的函数式接口时,可以使用@FunctionalInterface解决编译层面的错误。
常用函数式Java8中在java.util.function中引入了很多的函数式接口,这里介绍一下3个常用的函数式接口,
Predicate
Predicate接口定义一个名叫test的抽象方法,它接收泛型T对象,并返回一个boolean类型。经常使用到的地方是在流处理的过程中filter方法,满足条件的数据才会被过滤出来,例如我们上面的例子也可以改造成为Predicate函数式接口的形式。
public interface Predicate<T> {
boolean test(T t);
}
public static List<Student> filterStudent(List<Student> students,
Predicate<Student> predicate) {
List<Student> list = Lists.newArrayList();
for (Student student : students) {
if (predicate.test(student)) {
list.add(student);
}
}
return list;
}
Consumer
Consumer定义一个名叫accept的抽象方法,他接受泛型T的对象,没有返回值。如果你需要访问泛型对象T,并其进行修改,就使用Consumer。经常使用的地方就是常用的forEach方法。
public interface Consumer<T> {
void accept(T t);
}
void forEachOrdered(Consumer<? super T> action);
Function
Function定义一个叫apply的方法,他接受一个泛型对象T,返回一个泛型对象R。如果你需要定义一个Lambda表达式,将输入的对象映射到输出,就使用Function,经常使用到的地方就是常用的map方法。
public interface Function<T, R> {
R apply(T t);
}
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Lambda原理窥探