lambda表达式:https://www.cnblogs.com/haixiang/p/11029639.html
lambda表达式
lambda表达式是一个匿名函数,可以理解为一段可传递的代码。
public void test() {
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
}
public void test1() {
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
}
需求:过滤年龄大于30的学生,成绩大于90的学生
传统写法,for循环遍历比较返回。
优化一:策略者模式
1、定义比较接口
public interface Compare<T> {
boolean com(T t);
}
2、书写实现类
public class FilterByAge implements Compare<Student> {
@Override
public boolean com(Student student) {
return student.getAge() >= 22;
}
}
3、调用
filterStu(students,new FilterByAge());
# 成绩的筛选同样的实现方式书写即可
优化2:匿名内部类
省去接口实现的步骤直接使用匿名内部类
filterStu(students, new Compare<Student>() {
@Override
public boolean com(Student student) {
return student.getAge() > 22;
}
});
优化3:lambda表达式
List<Student> list = filterStu(students,(e) -> e.getAge() > 56);
// 打印输出
list.forEach((e)-> System.out.println(e.getAge()));
// 打印输出
list.forEach(System.out::println);
优化方式四:Stream API
直接基于原始数据去遍历,一句代码搞定
students.stream().filter((e) -> e.getAge() >22).forEach(System.out::println);
基础语法
- -> 操作符
将表达式lamda表达式拆分为两个部分,左侧为参数,右侧为操作执行
左侧对应抽象方法 右侧对应实现 - 无参函数
@Test
public void testL() {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("lamda!");
}
};
// 等价于,通过lamda表达式实现无参run方法
Runnable lamdaR = () -> System.out.println("lamda!");
}
注意:同匿名内部类一样使用同的变量只可读,不可写,因为变量会自动加上final,这是规定。
如下匿名内部类和lamda表达式都不能修改num的值
@Test
public void testL() {
int num;
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("lamda!");
}
};
// 等价于,通过lamda表达式实现无参run方法
Runnable lamdaR = () -> System.out.println("lamda!");
}
- 只有一个参数,()可以不写
List<Student> list = filterStu(students,(e) -> e.getAge() > 56);
List<Student> list = filterStu(students,e -> e.getAge() > 56);
- 两个参数、多条语句,并且有返回值
多条语句需要加大括号{}
Comparator<Integer> comparator = (x,y) -> {
System.out.println(x);
System.out.println(y);
return Integer.compare(x,y);
};
- 两个参数,一条语句,有返回值return和{}都可以不写
- lamda的表达式的参数列表可以省略不写,可以JVM可以通过上下文进行推断,也可以写上。
函数式接口
通过上面的例子可以发现,lamda表达式依赖于函数式接口,里面只能有一个抽象方法。
public interface Calculate {
int op(int a,int b);
}
@Test
public void testL() {
System.out.println(op(10,10,(a,b) -> a + b));
System.out.println(op(10,10,(a,b) -> a * b));
System.out.println(op(10,10,(a,b) -> a - b));
System.out.println(op(10,10,(a,b) -> a / b));
}
public int op (int a,int b ,Calculate calculate) {
return calculate.op(a,b);
}
接口申明方法,具体实现由lamda完成
Java四大内置函数式接口
- consumer:消费型接口
void accept(T t);
@Test
public void testL() {
int money = 100;
op(money,a -> a -= 10);
op(money,b -> b -= 100);
}
public void op (int a, Consumer<Integer> consumer) {
consumer.accept(a);
}
- Supplier :提供型接口
T get();
@Test
public void testL() {
List<Integer> list = new ArrayList<>();
// 获取随机数并加入集合
list.add(op(() -> (int)Math.random()));
}
public int op (Supplier<Integer> supplier) {
return supplier.get();
}
- Function<T,R> : 函数型接口
R apply(T t);
@Test
public void testL() {
op("liyong",(str) -> str.trim());
op("liyong",(str) -> str.toUpperCase());
}
public String op (String str,Function<String,String> function) {
return function.apply(str);
}
- Predicate :断言接口
Boolean test(T t);
@Test
public void testL() {
op("liyong",(str) -> str.equals("liyong"));
}
public boolean op (String str, Predicate<String> predicate) {
return predicate.test(str);
}
- 其他接口
方法引用
- 对象::实例方法名
方法已经被实现且返回值类型,参数列表与函数式接口的抽象方法保持一致
Student student = new Student(23,"liyong",888888888);
Supplier<Integer> supplier = () -> student.getAge();
// 等价于
Supplier<Integer> supplier = () -> student::getAge;
- 类::静态方法名
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
// 等价于
Comparator<Integer> comparator = Integer::compare;
- 类::实例方法名
// 使用规则,第一个参数是实例方法的调用者,第二个参数为实例方法的参数
BiPredicate<String,String> biPredicate = (x,y) -> x.equals(y);
BiPredicate<String,String> biPredicate = String::equals;
构造器引用
ClassName::new
由于Suppliers为无参,则调用无参构造
Supplier<Student> supplier =Student::new;
Student student = supplier.get();
数组引用
Function<Integer,String[]> function = String[]::new;
String[] strings = function.apply(10);