lambda表达式
函数式接口
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口(functional interface)
lambda表达式可以传递到函数式接口。
lambda表达式可以转换为接口。(函数式接口)
JavaAPI
-java.util.function
包中的函数式接口
BiFunciton<T,U,R>
:描述了参数类型为T和U而且返回类型为R的函数。例如
BiFunction<String,String,Integer> comp =
(first,second)->first.length() - second.length();
Predicate
pubilc interface Predicate<T>{
boolean test(T t);
//其他默认和静态方法
}
ArrayList
类有一个removeIf
方法,它的参数就是一个Predicate
。这个接口专门用来传递lambda表达式。
例如
从一个数组列表删除所有null值:
list.removeIf(e->e==null);
Supplier<T>
public interface Supplier<T>{
T get();
}
供应者(supplier)没有参数,调用时会生成一个T类型的值。供应者用于实现懒计算。
例如
LocalDate hireDay = Objects.requireNonNullElseGet(day, ()->LocalDate.of(1970,1,1));
requireNonNullElseGet
方法只在需要值时才调用供应者
例如:这个程序显示了如何对一个比较器和一个动作监听器使用lambda表达式。
public class LambdaTest {
public static void main(String[] args) {
String[] planets = {"zhangsan", "lisi", "wangwu", "zhaoliu", "wuqi","xiaoming"};
System.out.println(Arrays.toString(planets));
System.out.println("按字典顺序排序:");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));
System.out.println("按字符串长度排序:");
Arrays.sort(planets,(first,second)->first.length()-second.length());
System.out.println(Arrays.toString(planets));
Timer timer= new Timer(1000,event-> System.out.println("当前时间:"+new Date()));
timer.start();
//保持程序运行直到用户选择"OK"
JOptionPane.showMessageDialog(null,"是否退出?");
System.exit(0);
}
}
方法引用
只有当lambda表达式的体只调用一个方法而不做其他操作时,才能把lambda表达式重写为方法引用。
例如:
s->s.length() == 0
这里有一个方法调用。但是还有一个比较,所以这里不能使用方法引用
要用
::
操作符分隔方法名与对象或类名,有三种类型1.
object::instanceMethod
2.
Class::instanceMethod
3.
Class::staticMethod
1.第一种,方法引用等价于一个lambda
表达式,其参数要传递到方法。
例如
System.out::println
,对象是System.out
,所有这个方法表达式等价于x->System.out.println(x)
public interface Actor{//演员
void performance();//演出
}
public class Dancer{//跳舞
public void dancer(){System.out.println("舞蹈家在跳舞");}
}
public class ActorTest{
public static void main(String[] args){
//匿名内部类
/**Actor actor = new Actor(){
@Override
public void performance(){
new Dancer().dancer();
}
};*/
//lambda表达式
//Actor actor = ()->new Dancer().dancer();
//方法引用 对象 方法
Actor actor = new Dancer()::dancer;
actor.performance();
}
}
2.第二种,第一个参数会成为方法的隐式参数。
例如
String::compareToIgnoreCase
等同于
(x,y)->x.compareToIgnoreCase(y)
3.第三种,所有参数都传递到静态方法
例如
Math::pow
等价于(x,y)->Math.pow(x,y)
public interface ArraySorter{//数组排序接口
void sortDesc(int [] arr);//降序
}
public class ArrayTools{//数组工具类
public static void bubbleSort(int [] arr){
for(int i = 0;i<arr.length;i++){//冒泡排序,完成降序
for(int j = 0;j<arr.length-1-i;j++{
if(arr[j]<arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
public class ArraySorterTest{
public static void main(String [] args){
//要排序的数组
int [] numberArr={"2","4","1","6","5","3"};
//匿名内部类
/**ArraySorter as = new ArraySorter(){
@Override
public void sortDesc(int arr){
ArrayTools.bubbleSort(arr);
}
};*/
//lambda表达式
//ArraySorter as = arrays->ArrayTools.bubbleSort(arrays);
//方法引用 类名 方法名
ArraySorter as = ArrayTools::bubbleSort;
as.sortDesc(numberArr);
System.out.println(Arrays.toString(numberArr));
}
}
可以在方法引用中使用this参数和super
例如
this::equals
等同于x->this.equals(x)
public interface Calculator{//计算器
int calculate(int a,int b);
}
public class Person{
public int calculate(int num1,int num2){
//匿名内部类
/**Calculator c = new Calculator(){
@Override
public int calculate(int a,int b){
return Person.this.add(a,b);
}
}*/
//lambda表达式
// Calculator c = (a,b)->Person.this.add(a,b);
//方法引用 this 方法名
Calculator c = this::add;
return c.calculate(num1,num2);
}
private int add(int a,int b){return a+b;}
}
public class PersonTest{
public static void main(String[] args){
Person p= new Person();
int result = p.calculate(5,10);
System.out.println(result);
}
}
例如 super::equals
等同于x->super.equals(x)
public interface Customer{
void communicate();//业务交流
}
public class SoftEngineer{//软件工程师
//分析业务方法
public void analysisBusyness(){
System.out.println("软件工程师分析业务");
}
}
public class JavaProgrammer extends SoftEngineer{//Java程序员继承软件工程师
public void communicate(){//业务交流
//匿名内部类
/**Customer c = new Customer(){
@Override
public void communicate(){
JavaProgrammer.super.analysisBusyness();
}
}*/
//lambda表达式
//Customer c = ()->JavaProgrammer.super.analysisBusyness();
//方法引用 super 方法名
Customer c = super::analysisBusyness;
c.communicate();
}
}
public class Test {
public static void main(String[] args) {
JavaProgrammer programmer = new JavaProgrammer();
programmer.communicate();
}
}
构造器引用
构造器引用与方法引用很类似,只不过方法名为new。
例如Person::new
//学生类型对象的构建器
public interface StudentBuilder {
/**
* 根据给定的字符串构建出一个学生对象
* @param msg
* @return
*/
Student build(String msg);
}
public class Student {
private String name;
private int age;
public Student(String line){
String[] arr = line.split(",");
this.name = arr[0];
this.age = Integer.parseInt(arr[1]);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
// StudentBuilder builder = new StudentBuilder() {
// @Override
// public Student build(String msg) {
// return new Student(msg);
// }
// };
// StudentBuilder builder2 = msg-> new Student(msg);
StudentBuilder builder3 = Student::new;
Student stu = builder3.build("张三,20");
System.out.println(stu.toString());
}
}