java8之lambda表达式看这一篇就够了

 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流的处理。

  

 

posted @ 2019-02-24 22:48  浮华而已灬  阅读(297)  评论(0编辑  收藏  举报