JDK8 Lambda表达式介绍(一)

243 阅读3分钟

JDK8 Lambda表达式介绍

  1. 了解Open jdk 和 Oracle jdk
  2. JDK8 新特性
  • Lambda 新特性
  • 集合之Stream流式操作
  • 接口的增强
  • 并行数组排序
  • Optional中避免Null检查
  • 新的时间和日期API
  • 可重复注解
  1. Open JDK 官网介绍OpenJdk官网

使用匿名内部类存在的问题

当需要启动一个线程去完成任务时,通常会通过Runable接口来定义任务内容,或使用Thread类类启动该线程.

传统写法如下
 public static void main(String[] args) {
      
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("新线程执行代码啦");
            }
        }).start();
    }

由于面向对象的语法要求,首选创建一个Runable接口的匿名类对象来指定线程要执行的任务内容,再将其交给一个线程来启动.

代码分析

对于Runable的匿名内部类用法,可以分析出几点内容:

  • Thread类需要Runable接口作为参数,其中的抽象run()是用来指定线程任务内容的核心
  • 为了指定run()的方法体,不得不需要Runable接口的实现类
  • 为了省去定义一个Runable实现类的麻烦,不得不使用匿名内部类
  • 必须覆盖重写抽象run方法,所以方法名称、方法参数、方法返回值不得不在写一遍,且不能写错
  • 实际上,似乎只有方法体是关键所在

lambda体验

lambda是一个匿名函数,可以理解为一段可以传递的代码

lambda表达式写法,代码如下

借助java8的全新语法,上述Runable接口的匿名内部类写法可以通过更简单的lambda表达式达到相同的效果

 public static void main(String[] args) {
        new Thread(()->{
            System.out.println("新线程执行代码啦");
        }).start();
 }

这段代码和刚才执行效果是完全一样的,可以在jdk8或更高的编译级别下通过.从代码的语义中可以看出,我们启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定. 我们只需要将要执行的代码放大到一个lambda表达式中,不需要定义类,不需要创建对象.

我们可以理解 Lambda相当于对接口抽象方法的重写

lambda的优点

简化匿名内部类的使用,语法更加简洁

Lambda省去面向对象的条条框框,Lambda表达式标准格式由3个部分组成:

(参数类型 参数名) -> {
    代码体
}

格式说明

  • (参数类型 参数名): 参数列表
  • {代码体}: 方法体
  • ->: 箭头,分割参数和方法体的

Lambda与方法的对比

匿名内部类

 public void run() {
    System.out.println("新线程执行代码啦");
 }

Lambda表达式

() ->{  System.out.println("Lambda执行代码啦"); }

无参数无返回值的Lambda

掌握了Lambda的语法,我们来通过一个案例熟悉Lambda的使用

public interface Swimmable {
    public abstract  void swimming();
}
public class demo01LambdaUse {
    public static void main(String[] args) {
        goSwimming(new Swimmable() {
            @Override
            public void swimming() {
                System.out.println("我是匿名内部类的游泳");
            }
        });
  
        goSwimming( (()->{
            System.out.println("我是lambda的游泳");
        }));
    }

  

    //参数无返回值的Lambda表达式
    private static void goSwimming(Swimmable swimmable) {
        swimmable.swimming();
    }
}

有参数有返回值的Lambda

下面举例演示java.util.Comparator<T>接口的使用场景代码,其中抽象方法定义为:

  • public abstract int compare(T o1, T o2) 当需要对一个对象集合进行排序时, Collections.sort()需要一个Comparator接口实例来指定排序的规则

传统写法

public class Person {
    private  String name;
    private int age;
    private double height;

   ... 省略部分代码
}
package com.example.jdk.demo01Lamdba;

import java.util.*;

/**
 * @author meteor
 */
public class demo01LambdaParam {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("刘德华", 55, 178.7));
        personList.add(new Person("张学友", 56, 179.7));
        personList.add(new Person("郭富城", 57, 177.7));
        personList.add(new Person("黎明", 58, 176.7));

        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        
        for (Person person : personList) {
            System.out.println(person);
        }    
    }
}

Lambda 写法

package com.example.jdk.demo01Lamdba;

import java.util.*;

/**
 * @author meteor
 */
public class demo01LambdaParam {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("刘德华", 55, 178.7));
        personList.add(new Person("张学友", 56, 179.7));
        personList.add(new Person("郭富城", 57, 177.7));
        personList.add(new Person("黎明", 58, 176.7));

        Collections.sort(personList,(Person o1, Person o2)->{
            return o2.getAge() - o1.getAge();
        });
        
        for (Person person : personList) {
            System.out.println(person);
        }      
    }
}