前言
在jdk1.8的时候,为了偷懒,为了程序的更加简洁,程序员在这个时候引入了Lambda表达式。刚开始看的时候必然会觉得难得雅痞,但熟悉以后便可以像写一个HelloWorld那么简单.
在讲Lambda之前,就需要知道什么是函数式接口
函数式接口
函数式接口本质上就是一个只定义了一个抽象方法的接口。为了更好的区别,我们需要加上注解 @FunctionalInterface(也可以不加,这只是为更好识别某个接口是否为函数式接口)
@FunctionalInterface
public interface LambdaTest(){
void test();
}
在java8中,Java为我们提供了四个比较常用的函数式接口
接口 | 抽象方法 | |
---|---|---|
消费性接口 | Consumer< T > | void accept(T t) |
供给型接口 | Supplier< T > | T get() |
函数型接口 | Function<T ,R > | R apply(T t) |
断定型接口 | Predicate< T > | boolean test(T t) |
从名字就可以得出其作用
Lmabda表达式
Lambda表达式实质
Lmabda表达式的实质是作为函数式接口的实例
格式
先举一个例子
这里我用的是自定义的函数式接口,但其实用Java事先给我们的更加方便
@FunctionalInterface
interface Person{
void eat();
}
public class test{
public static void main(String arg[]){
//用以前的老办法(而且是比较快、代码量比较少的一种)
Person student = new Person(){
@Override
public void eat(){
System.out.println("学生应该多吃点好的!");
}
};
student.eat();
System.out.println("------------华丽丽的分隔符------------");
//用Lambda表达式来写
Person student1 = () -> System.out.println("学生应该多吃点好的!");
stuendt1.eat();
//看,是不是简单了许多。但对于刚学的来说,还不太适应.
}
}
输出结果
一般格式(其实还有好多种,待会慢慢讲)
Person student1 = () -> System.out.println(“学生应该多吃点好的!”);
分析:
-> : 这个符号为成为 lambda操作符 或 箭头操作符
->左边: lambda形参列表(其实就是接口中抽象方法的形参列表),且如果Lambda形参列表只有一个参数时,其一对()也可以省略
->右边:lambda体(其实就是重写的抽象方法的方法体),且需要用一对{}包裹;如果Lambda体只有一条执行语句的时候(可能是return 语句),则可以省略这一对{}和return关键字
所以,这样的格式就可以分为6种.
六种格式的举例
语法格式一:Lambda形参列表无参,也无返回值
利用Runnbale接口,这个接口也是一个函数式接口
其抽象方法是void run();
public class Test1{
public static void main(String args[]){
Runnable r1 = new Runnable(){
@Override
public void run(){
System.out.println("格式: () -> 执行语句 ");
}
};
r1.run();
System.out.println("------------华丽丽的分隔符------------");
//使用Lambda表达式
}
}
输出结果:
语法格式二:Lambda形参列表 需要一个参数,但是无返回值
这个时候就可以使用Java提供给我们的那个消费型接口Consumer,抽象方法 void accept(T t)
public class Test1{
public static void main(String args[]){
Consumer<String> c1 = new Consumer<>(){
@Override
public void accept(String s){
System.out.println(s);
}
};
c1.accept("格式 (T t) -> System.out.println(t)");
//用Lambda表达式
Consumer<String> c2 = (String s) -> System.out.println(s);
c2.accept("格式 (T t) -> System.out.println(t)");
//输出结果: (T t) -> System.out.println(t)
}
}
语法格式三:数据类型可以省略,因为可有编译器推断得出,称为"类型推断"
以上面的例子为例,还可以省略
//用Lambda表达式
Consumer<String> c3 = (s) -> {System.out.println(s);};
c3.accept("格式 (s) -> {System.out.println(s)}")
稍微解释一下类型推断
//原来写代码时,用泛型时,比如
Consumer<String> c1 = new Consumer<>(){
//原应是Consumer<String> c1 = new Consumer<String>(){
//现在省略了在后面再次声明String的功夫
@Override
public void accept(s){
//在这里也可以直接写s
System.out.println(s);
}
};
语法格式四:->左边的形参列表若只需要一个参数,参数的小括号可以省略
//用Lambda表达式
Consumer<String> c3 = s -> System.out.println(s);
c3.accept("格式 s -> {System.out.println(s)}")
语法格式五:->右边的方法体只有一句,右边的括号也可以省略
//用Lambda表达式
Consumer<String> c3 = s -> System.out.println(s);
c3.accept("格式 s -> System.out.println(s)")
语法格式六:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值,
这个时候就需要写全了
Comparator<Integer> c1 = new Comparator<>{
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
}
};
//用Lambda表达式
Comparator<Integer> c2 = (o1 ,o2) -> {
System.out.println(o1);
System.out.println(o2);
return Integer.compare(o1,o2)
};
目前为止,Lambda表达式的一部分就讲完了。