java8增加了许多新特性,其中lambda表达式可以说为最重要的特性之一,本文将从如下几个方面来学习lambda:
1、lambda表达式的基本定义
2、lambda表达式的语法
3、lambda表达式基本示例
一、何为lambda表达式?
简单点说lambda为一种匿名函数,它既没有名字也没有声明的方法、访问修饰符和返回值等。它允许将函数作为方法的参数进行传递。
二、基本语法:lambda通常包含如下几种书写方式
() -> expression
() -> { statement }
() -> { statements }
(arg1,arg2) -> { statement }
(Type arge1,Type arge2) -> { statement }
三、jdk内置的函数式接口以及基本示例介绍
jdk内置了如下四大函数式接口,在java.util.function包下可以找到:
1、Function 接收一个参数类型 T , 返回类型 R ,适用于包装、修改等操作
@FunctionalInterface public interface Function<T, R> { R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } static <T> Function<T, T> identity() { return t -> t; } }
下面的代码演示了如何获取一个学生的所有名字:
public static void main(String[] args) { Student student1 = new Student("a",11); Student student2 = new Student("b",12); Student student3 = new Student("c",21); Student student4 = new Student("d",1); List<Student> students = new ArrayList <>(); students.add(student1); students.add(student2); students.add(student3); students.add(student4); List < String > names = filterStudent(students , student -> student.getName()); names.forEach((name)-> System.out.println(name)); //输出结果:a b c d } public static <T,R> List<R> filterStudent(List<T> list, Function<T,R > function){ List<R> names = new ArrayList <>(); for (T t : list) { names.add(function.apply(t)); } return names; }
2、Consumer 接收一个参数 类型T ,无返回值 ,适用于遍历等操作
@FunctionalInterface public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
适用于遍历,最典型的 foreach 示例:
1 List<String> list = new ArrayList <>(); 2 list.add("a"); 3 list.add("b"); 4 list.add("c"); 5 list.add("d"); 6 list.forEach((str)->System.out.println(str)); 7 //直接调用类的方法进行输出 8 list.forEach(System.out::println); 9 10 list.forEach((str)->{ 11 //若为一个对象,可以进行其余的保存、更新等操作 12 System.out.println(str); 13 });
3、Predicate 接受一个参数T ,返回boolean,适用于判断过滤等操作
1 @FunctionalInterface 2 public interface Predicate<T> { 3 4 boolean test(T t); 5 6 default Predicate<T> and(Predicate<? super T> other) { 7 Objects.requireNonNull(other); 8 return (t) -> test(t) && other.test(t); 9 } 10 11 12 default Predicate<T> or(Predicate<? super T> other) { 13 Objects.requireNonNull(other); 14 return (t) -> test(t) || other.test(t); 15 } 16 17 18 static <T> Predicate<T> isEqual(Object targetRef) { 19 return (null == targetRef) 20 ? Objects::isNull 21 : object -> targetRef.equals(object); 22 } 23 }
下面的代码演示了 Predicate 接口的基本用法:
1 public static void main(String[] args) { 2 Student student1 = new Student("a",11); 3 Student student2 = new Student("b",12); 4 Student student3 = new Student("c",21); 5 Student student4 = new Student("d",1); 6 List<Student> students = new ArrayList <>(); 7 students.add(student1); 8 students.add(student2); 9 students.add(student3); 10 students.add(student4); 11 List < Student > students1 = testStudent(students , student -> student.getAge() > 11); 12 students1.forEach(student -> System.out.println(student.getName())); 13 //输出结果:b c 14 } 15 16 public static <T> List<T> testStudent(List<T> list , Predicate<T> function){ 17 List<T> newList = new ArrayList <>(); 18 for (T t : list) { 19 if(function.test(t)){ 20 newList.add(t); 21 } 22 } 23 return newList; 24 }
4、Supplier 无参数,返回一个结果
1 @FunctionalInterface 2 public interface Supplier<T> { 3 4 T get(); 5 6 }
从上面的四个函数式接口中我们可以总结出如下几点:
1、函数式接口一般都有 @FunctionalInterface 注解标识,但是此注解并非强制需要,如果不标注的话编译器将无法识别只能拥有一个未实现的方法
2、函数式接口之接受唯一的 public 方法 ,但是允许有 default 方法 、静态方法以及 父类Object的方法(如果声明第二个public方法会直接报错,大家可以试一下)。
函数式接口的使用一般会配合 java中Stream Api进行使用,下篇文章将会讲解java中Stream流的处理。