为什么使用Lambda表达式?
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(像数据一样传递代码),写出更简洁灵活的代码,同时提升java语言表达能力。
当然又整了这么多花里胡哨的东西,还是上点代码吧,毕竟程序员怎么能不用代码提提神呢。
@Test
public void test1() {
//匿名内部类写法
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
//传入比较器
TreeSet<Integer> treeSet = new TreeSet<Integer>(comparator);
//Lambda表达式写法
Comparator<Integer> comparatorLambda = (x,y) ->Integer.compare(x,y);
//传入比较器
TreeSet<Integer> treeSetLambda = new TreeSet<Integer>(comparatorLambda);
}
记得当时用匿名内部类感觉这是什么东西啊,现在终于出了个Lambda表达式来优化了,是不是简洁多了(哈哈,es6的箭头函数的既视感)。
那么现在我们来学习以下这个Lambda表达式吧。
@Test
/**
* 一、Lambda 表达式基本语法,基于“->” 把lambda分为左右两个部分
* 左边 lambda参数列表 接口中方法的参数列表
* 右边 lambda表达体,表达式中所需要实现的功能 实现这个抽象方法
*
* 语法格式一:无参数,无返回值
* () -> System.out.printIn("Hello Lambda")
*
* 语法格式二:一个参数,无返回值;若只有一个参数,小括号可以不写
* (arg) ->System.out.printIn("Hello Lambda")
* arg ->System.out.printIn("Hello Lambda")
*
* 语法格式三: 有两个或者以上参数,有返回值,lambda体中有多条语句
* 注:当lambda体中只有一条语句,大括号和return都能省略不写
* 注:表达式的参数列表数据类型可以省略不写,因为jvm可以通过上下文推断出来
* Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y)
*
*在网上关于这个还看到一个很有意思的总结对联
* 上联:左右遇一括号省
* 下联:左侧推断类型省
* 横批:能省则省
*
* 二、Lambda表达式需要“函数式接口”的支持
* 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface
* 修饰来检查是否是函数式接口,一般来说new 一个这个对象只需要重写一个方法的就可以
*
*/
public void testLambda(){
//语法格式一
//先找个接口,里面的方法是无参,无返回值的
//原来实现的方法
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello runnable");
}
};
Runnable r = () -> System.out.println("Hello Lambda!");
runnable.run();
System.out.println("----------");
r.run();
//-----------------------------------------------
//语法格式二
//原本格式
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
Consumer<String> c = s -> System.out.println(s);
c.accept("Hello Lambda 来了");
//-------------------------
//语法三
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
};
Comparator<Integer> comparator = (x,y) ->{
System.out.println("为了多条语句");
return Integer.compare(x,y);
};
//以上就是lambda的基本语法和介绍了,现在我们来举个实际运用中的例子
//现在需要对一个数进行各种运算,我们来用lambda表达式来实现
//原始写法
Calculation calculation = new Calculation(){
@Override
public Integer getValue(Integer num) {
//现在想做一个乘法运算
return num*num;
}
};
System.out.println("计算结果"+getValue(10,calculation));
//Lambda表达式写法
Integer sum = getValue(10,num -> num*num);
System.out.println("计算结果Lambda写法"+ sum);
}
//首先定义一个用来计算的接口,来表明这个数字要进行的运算公式
@FunctionalInterface
public interface Calculation{
public Integer getValue(Integer num);
}
//定义一个运算方法
public Integer getValue(Integer num,Calculation calculation){
return calculation.getValue(num);
}
以上就是lambda表达式的基础语法和应用了,当然,lambda表达式还不止这些,接下来,我们来看看进阶语法。
@Test
/**
* 一、方法引用:若Lambda体中的内容方法已经实现了,我们可以使用“方法引用”
* (可以理解为方法引用是Lambda表达式的另外一种表现形式)
*
* 主要有三种语法格式;
* 对象::实例方法名
* 类::静态方法名
* 类::实例方法名
*
* 注意:
* 1.Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
* 2.若 Lambda 参数列表中的第一参数是 实例方法的调用者,而第二参数是实例方法的参数时,可以使用ClassName::method
*
* 二、构造器引用
* ClassName::new
*
* 注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!
*
* 三、数组引用
* Type::new
*/
public void testLevelLambda(){
//一
//对象::实例方法名
// void accept(T t);单参数,无返回值
// public void println(String x) {
// synchronized (this) {
// print(x);
// newLine();
// }
// }单参数,无返回值
Consumer<String> consumer = (str) -> System.out.println(str);
//方法引用写法,前提是lambda体的方法返回值和参数和你方法引用的函数的参数列表返回值和参数一致
Consumer<String> con = System.out::println;
con.accept("方法引用写法");
consumer.accept("原本写法");
//类::静态方法名
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
//函数引用
Comparator<Integer> com = Integer::compare;
//类::实例方法名
BiPredicate<String,String> biPredicate = (x,y) -> x.equals(y);
//函数引用
BiPredicate<String,String> bip = String::equals;
//-----------------------------------
//二
//构造器引用
//原版方式
Supplier<Student> supplier = () -> new Student();
//构造器引用方式
Supplier<Student> studentSupplier = Student::new;
//---------------------------------
//三
//数组引用
//原版写法
Function<Integer,String[]> function = (x) -> new String[x];
String[] strings = function.apply(10);
System.out.println(strings.length);
//数组引用写法
Function<Integer,String[]> integerFunction = String[]::new;
String[] strings1 = integerFunction.apply(20);
System.out.println(strings1.length);
}