JDK8新特性之Lambda
1 什么是lambda表达式
Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升。把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。其实就是个匿名函数。
2 为什么要用lambda表达式
可以简化代码增加代码的可读性
3 Lambda表达式的好处
lambda表达式对接口的一个简单实现,本质就是简化匿名内部类的代码
3.1 传统的匿名内部类的写法
public static void main(String[] args) {
Thread thread=new Thread(new Runnable(){
@Override
public void run() {
System.out.println("这是一个匿名内部类");
}
});
thread.start();
}
这样的写法代码过于的笨重为了简化开发所以jdk8推出了匿名内部类的另一种写法,既Lambda表达式
3.2 Lambda表达式的学法
public static void main(String[] args) {
Thread thread=new Thread(()-> System.out.println("这是一个匿名内部类"));
thread.start();
}
比上面的代码是不是少了很多,把垃圾代码都给删除了,这也许就是Lambda的好处把。
4 Lambda表达式限制
接口只有一个抽象方法(必须要实现的,不是default修饰的)。
Java8对接口加了一个新特性:default,修饰接口方法,就可以有默认实现,这样实现类可以实现该方法也可以不实现。
@FunctionalInterface(这个可以不写但是为了规范,这个一般都要写上)
修饰函数式接口的,接口中抽象方法只能有一个。
5 基础语法:
- 操作符:-> -
- 左侧:参数列表
- 右侧:执行代码块 / Lambda 体
6 语法格式
主要有4中语法格式:
1.方法是无参数无返回值
()-> System.out.println(“这是一个匿名内部类”);
列如:下面Runnable()接口
public static void main(String[] args) {
Thread thread=new Thread(()-> System.out.println("这是一个匿名内部类"));
thread.start();
}
2.方法是一参数无返回值的
(x)-> System.out.println(“这是一个匿名内部类”);
Consumer<String> consumer=(a) -> System.out.println("这是一个消费接口,有参无返回值");
3.如果只有一个参数,那么括号可以省略,但是一般开发中还是不要省略
x-> System.out.println(“这是一个匿名内部类”);
Consumer<String> consumer1 = a -> System.out.println("这是一个消费接口,有参无返回值");
4.方法有多个参数,有返回值,方法体中不止一条语句
x-> {
System.out.println(“这是一个匿名内部类”);
System.out.println(“这是一个匿名内部类”);
return a;
}
Comparator<Integer> comparator=(a, b) -> {
System.out.println("多参数,有返回值");
if(a>b){
return a;
}else{
return b;
}
};
方法有多个参数,有返回值,方法体中一条语句
Comparator<Integer> comparator=(a, b) -> Integer.compare(a, b);
7 案例
比较两个数的大小,放回值
public interface MyFun {
Integer count(Integer a, Integer b);
}
public static void main(String[] args) {
//出入两个数字,输出大的数字
MyFun myfun = (a, b) -> {
if (a > b) {
return a;
} else {
return b;
}
};
System.out.println(myfun.count(1, 2));
//出入两个数字,输出小的数字
MyFun mix = (a, b) -> {
if (a < b) {
return a;
} else {
return b;
}
};
System.out.println(mix.count(1, 2));
}
在上面的案列中我们需要一个接口,这个接口的方法是传入一个参数,返回一个值,这样的接口还要我们自己写,是不是太麻烦了,比如我们要一个方法出入参数不要返回值,那么我们又要定义这样的接口。而jdk8为了方便用户的使用帮我们定义了一些内置的接口让我们使用,这样我们就不用再去定义接口了,大大减少了开发的效率。下面介绍下jdk中内置的接口
8.函数式接口
比如上面的列子,我们就可以用函数行接口使用下
BiFunction<Integer,Integer,Integer> max=(a,b) ->{
if (a > b) {
return a;
} else {
return b;
}
};
System.out.println(max.apply(1, 2));
这个就变成这样写了不用自己去定义接口,当然BiFunction不是四大内置的接口,当四大内置接口不够时,还有些扩展接口。
8.1 消费型接口
@Test
public void test01(){
//Consumer
Consumer<Integer> consumer = (x) -> System.out.println("消费型接口" + x);
//test
consumer.accept(100);
}
8.2提供型接口
@Test
public void test02(){
List<Integer> list = new ArrayList<>();
List<Integer> integers = Arrays.asList(1,2,3);
list.addAll(integers);
//Supplier<T>
Supplier<Integer> supplier = () -> (int)(Math.random() * 10);
list.add(supplier.get());
System.out.println(supplier);
for (Integer integer : list) {
System.out.println(integer);
}
}
8.3 函数型接口
@Test
public void test03(){
//Function<T, R>
String oldStr = "abc123456xyz";
Function<String, String> function = (s) -> s.substring(1, s.length()-1);
//test
System.out.println(function.apply(oldStr));
}
8.4 断言型接口
@Test
public void test04(){
//Predicate<T>
Integer age = 35;
Predicate<Integer> predicate = (i) -> i >= 35;
if (predicate.test(age)){
System.out.println("你该退休了");
} else {
System.out.println("我觉得还OK啦");
}
}
9 方法的引用
如果Lambda中有方法已经实现了那么我们就可以用方法的引用了
主要语法格式
- 对象::方法名
- 类::静态方法名
- 类::实例方法名
注意调用的方法名的返回值参数要你,函数式接口的返回值一致
public static void test01(){
//Consumer
Consumer<Integer> consumer = (x) -> System.out.println("消费型接口" + x);
//另一种写法
Consumer<Integer> consumer1 = Lambda::consumer;
//test
consumer.accept(100);
}
public static void consumer(Integer a){
System.out.println("消费型接口" + a);
}
10 构造器的引用
格式:
- ClassName :: new
@Test
public void test04(){
Supplier<List> sup1 = () -> new ArrayList();
Supplier<List> sup2 = ArrayList::new;
}
主要构造器的方法与参数列表中的方法保持一致。Supplier 接口返回List集合,我们需要给他一个集合所以就new了一个集合给他。