jdk8-lambda表达式

后端 / 笔记 / 2021-09-15

什么是lambda表达式

lambda 表达式是一个匿名函数
简化匿名内部类的调用

lambda表达式规范

  • 接口中只有一个抽象方法
  • 函数接口中定义Object类中的方法
  • 使用默认或静态方法
  • @FunctionalInterface 表示该接口为函数式接口
  • ()->{}

image.png

package jdk8.lambda;

@FunctionalInterface
public interface Closeable {
    void close();
    // 允许存在Object类中的方法
    String toString();
}

package jdk8.lambda;

public interface Callable {
    void call();
}

package jdk8.lambda;

public class Main {
    public static void main(String[] args) {
        // 匿名内部类写法
        Callable callable = new Callable() {
            @Override
            public void call() {
                System.out.println("call");
            }
        };
        callable.call();

        // lambda表达式写法
        // ((InterFace)()->{}).method()
        ((Callable) () -> System.out.println("hello,world")).call();


        // 匿名内部类的方式
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        // lambda表达式方式
        new Thread(()->{
            System.out.println(Thread.currentThread().getName());
        }).start();


        // 函数式编程接口
        ((Closeable)()->System.out.print("close")).close();
    }
}

lambda表达式写法

  • (): 参数列表
  • ->: 分隔符
  • {}: 方法体
  • 函数参数列表 不需要写类型 只需要写参数名称

// 无参lambda表达式
()->{
	// doSomething
}

// 带参lambda表达式
(a,b)->{
	// dSomething
}

不带参数的lambda表达式

// 不带参数的lambda表达式
new Thread(()->System.out.println("thread running...")).start();
thread running...

带参数的lambda表达式

package jdk8.lambda;

@FunctionalInterface
public interface Animal {
    void bark(String tag);
}

// 带参数的lambda
((Animal) tag -> System.out.println(tag + ":wof ~")).bark("petter");
petter:wof ~

lambda表达式精简方案

方案1

((InterFaceName)(paramList)->).method();

  • InterFaceName: 接口名称
  • paramList: 参数列表
  • methodBody: 方法体
  • method: 要调用的方法
// lambda表达式精简
Animal animal = (tag) -> {
	System.out.println(tag);
};
animal.bark("petter");
        
        
// 方案1
// ((InterFaceName)(paramList)->{methodBody}).method();
((Animal)(tag)->{
	System.out.println(tag);
}).bark("petter");

/**
* - InterfaceName: 函数接口名称
* - paramList: 参数列表
* - methodBody: 方法体
*/

方案2

如果方法体内只有一行语句则不需要{},并且也不需要写return语句

// 方案2 如果方法体内只有一行语句则 可以去掉括号
((Animal) (tag) -> {
	System.out.println(tag);
}).bark("petter");

((Animal) (tag) ->System.out.println(tag)).bark("petter");

方案3

方法引入

lambda表达式实战

forEach

ArrayList forEach 遍历

ArrayList<String> strings = new ArrayList<>();
strings.add("tom");
strings.add("jerry");
strings.add("wangcai");


// 传统遍历方案 匿名内部类
strings.forEach(new Consumer<String>() {
  @Override
  public void accept(String s) {
    System.out.println(s);
  }
});

// 但是通过分析 我们发现 他是一个 函数式接口 Consumer
// 既然它满足 函数式接口规范 那么他必然可以使用 lambda表达式

strings.forEach(s-> System.out.println(s));

集合排序

// 集合排序
ArrayList<Integer> integers = new ArrayList<>();
integers.add(99);
integers.add(5);
integers.add(7);
integers.add(180);
integers.add(130);



// 传统解决方案 Comparator 接口 匿名内部类
// 同样得知 是一个 函数式接口
integers.sort(new Comparator<Integer>() {
  @Override
  public int compare(Integer o1, Integer o2) {
    return o1-o2;
  }
});


// 改进
integers.sort((o1,o2)->o1-o2);


integers.forEach(s-> System.out.println(s));

总结

  • lambda表达式是为了简化匿名内部类
  • lambda表达式的使用一定要满足函数式接口
  • 语法:()->{}
  • 如果方法体内只有一行语句可以省略括号和return
  • lambda表达式的出现极大地简化了代码