Skip to content
Go back

Lambda 表达式

Lambda 式 Java8 中一个重要的功能,它可以很简洁地表示一个行为或传递代码,现在我们可以把 Lambda 表达式看作匿名功能,它基本上就是没有声明名称的方法,但和匿名类一样,它也可以作为参数传递给一个方法。JDK 本身也提供了大量的 FunctionInterface 来支持这一特性。

如何创建一个接口使用 Lambda 表达式


创建接口之前,首先我们需要了解 Lambda 到底是什么,我觉得一位老师说的最为贴切,* 普通方法的参数是参数值,泛型的参数是参数的类型,Lambda 的参数是一段代码 *,当然这句话只能用来理解(因为运行时没有泛型的概念),下面将用 ArrayList.forEach() 来展示为什么说 Lambda 传递的是一段代码。

//	在没有Lambda之前
for(String s: list) {
  System.out.pringln(s);
}

//	Lambda之后较为繁琐的写法,从这是不是就能看出来为什么说传递的是代码段了呢
//	Consumer是一个接口,而之后的代码段是接口的实现
Consumer<String> consumer = (item) -> {System.out.println(item);};
list.forEach(consumer);

//	当参数列表为一个时,可以省略参数的括号
Consumer<String> consumer = item -> {System.out.println(item);};

//	当代码只有一行时,可以省略花括号
Consumer<String> consumer = item -> System.out.println(item);

//	当参数全部作为代码段的参数且只有一行时,可以省略方法参数,该种方式称之为方法引用
Consumer<String> consumer = System.out::println;

实际上创建一个这样的接口非常简单,下面创建一个来模拟一下forEach的操作。

第一步:声明接口

@FunctionInterface表示这是一个函数式接口,接口中只能有一个方法(不包含默认和静态方法),使用该接口后将会执行更为严格的校验,不符合要求会直接编译报错,RunnableCompable等均是FunctionInterface

//	声明一个接口
@FunctionInterface
public interface MyInterface{
  void execute(String);
}

第二步:在自己的集合类中创建forEach方法(实验效果忽略泛型)

void forEach(MyInterface interface){
  //array为list中维护的数组
  for(String s:array){
		interface.execute(s);
  }
}

第三步:方法调用

MyInterface interface = (item) -> {System.out.println(item);};
MyList.forEach(interface);

这样实际上就完成了一个接口的创建和lambda方式的调用,但是MyInterface实际上不需要我们手动创建,JDK中已经提供了几个最为常见的基础接口,在集合的stream操作中几乎处处可见他们的影子

//	java.util.function.Function下的apply方法,一般用来根据原值返回一个新值
R apply(T t);

//	java.util.function.Consumer下的accept方法,与apply方法类似,只是无返回值
//	我们所创建的MyInterface就可以用这个代替了,ArrayList的forEach方法就是用的Consumer接口
void accept();

//	java.util.function.Predicate下的test方法,一般用来做逻辑判断并返回boolean
boolean test();

//	java.util.function.Supplier下的get方法,一般按照lambda中的方法返回一个新值
T get();

常见的Stream操作

filter

注意返回true表示元素满足条件,false则表示剔除

//	筛选出年龄为18的
list.stream().filter(item -> 18 == item.getAge).collect(toList());
distinct

distinct ()是按照equals ()方法去重的

list.stream().distinct().collect(toList());
limit & skip

limit ()表示获取前N个元素,skip ()表示跳过前N个元素

//	获取前5个元素
list.stream().limit(5).collect(toList());

//	剔除前5个元素
list.stream().skip(5).collect(toList());
map

map ()表示对元素的转换,可以将原先的元素转换成另一种形式

//	将学生的年龄去重之后组成新的List
list.stream()
	.map(Student::getAge)
	.distinct()
	.collect(toList());
groupingBy

按照给定的逻辑分组

//	按照年龄分组,key为年龄,value为该年龄段的学生
Map<Integer,List<Student>> map = list.stream()
  .collect(Collectors.groupingBy(Student::getAge()));
	
//	按照年龄分组,获取每个年龄的人数
Map<Integer,Long> map = list.stream()
  .collect(Collector.groupingBy(Student::getAge,Collector.counting()));