lambda表达式

721 阅读2分钟

函数式编程思想

可传递的代码块,可以在以后执行一次或多次(将一个代码块传递到某个对象,这个代码块会在将来某个时间调用)

lambda表达式看作是一个函数,而不是一个对象

λ 知道存在,但是不知其值

lambda表达式的语法

参数,箭头(->)以及一个表达式,并包含显示return语句(可忽略)

  • 标准版
(String first,String second) -> first.length() - second.length()
  • 可以包含 显式的return 语句
(String first,String second) -> {
  if(first.length() < second.length()) return -1;
  else if(first.length() > second.length()) return 1;
  else return 0;
}
  • 没有参数,提供空括号(无参)
() -> {
  for ( int i = 0; i <= 100; i++) {
    System.out.println(i);
  }
}
  • 如果可以推导出 lambda 表达式的参数类型,可以忽略参数类型
(first,second) -> first.length() - second.length()
  • 方法只有一个参数,参数的类型可以推导得出,还可以忽略小括号
event -> System.out.println("The time is" + new Date());
  • 无需指定 lambda 表达式的返回类型,返回类型有上下文推导得出,忽略 return
(String first,String second) -> first.length() - second.length() // 返回值为int 

何时使用 lambda表达式

通过表达式来代替功能接口,编译器会将表达式的参数及返回值与需要传入的接口中的方法表进行比对,发现存在匹配的方法,则重写实现这个接口中的方法,省去了建立接口实现的过程

断言接口

java.util.function.Predicate

public interface Predicate<T> {
    boolean test(T t);
}

从数组列表删除所有的null值,removeIf方法的参数是Predicate

list.removeIf(e -> e == null);

方法引用

已经有现成的方法可以完成你想要传递到其他代码的某个动作,此时可以使用方法引用,而不使用 lambda。使用::进行编写。

Timer t = new Timer(1000, e -> System.out.println(e)); 
// 等价与
Timer t = new Timer(1000, System.out::println);
// 不考虑字母大小写进行排序
String[] strs = {"tom", "jeck", "genny", "lufe"};
Arrays.sort(strs, String::compareToIgnoreCase);

3种情况

  • object::instanceMehtod 对象::方法
  • Class::staticMethod 类::静态方法
  • Class::instanceMethod 类::方法

前两种情况,等价与提供方法参数的 lambda表达式。 第三种情况,作为外部调用方法的第一个参数会作为函数式的目标对象,从而调用其内部的普通方法,编译器通过上下文语义解析得到。