lambda表达式

前言

lambda表达式是java8所引入的新特性之一,用于简化java中将某些功能传递给某些方法的功能举实现。将lambda当做一个变量,使得java能够写出函数式编程风格的代码。函数式编程风格在代码简洁性、可读性方面较原先的匿名类实现有很大的提升。

举个栗子-创建一个线程

  • 匿名类实现:
new Thread(new Runnable() {
     @Override
     public void run() {
         try {
             System.out.println("running");
             TimeUnit.SECONDS.sleep(5);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
 }).start();
  • lambda表达式实现:
new Thread(() -> {
    try {
        System.out.println("running");
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

通过上述栗子可见,使用lambda表达式具有比使用匿名类更简洁的代码编写风格。

那么lambda表达式,在java代码中是如何呈现的呢?本文将逐一展开介绍

1. lambda表达式结构

首先,顾名思义lambda表达式是一种没有声明方法的匿名函数表示形式,也就意味着该方法没有访问修饰符、返回值声明及方法名。

  1. lambda表达式结构:
    (arg1…) -> { body }
  • arg1 -> body ,body只有一条语句
  • () -> { body }
  • (arg1, arg2…) -> { body }
  • (type1 arg1, type2 arg2…) -> { body }
  1. 双冒号( :: )结构
    双冒号操作符在java中表示方法引用,可作为lambda调用特定方法的缩写,并且具有更好的可读性
    目标引用::方法
  • String::toString
  • System.out::println

2. @FunctionalInterface注解

@FunctionalInterface注解是java8中新引入的一个注解,用于指示接口类型支持函数式编程风格接口。@FunctionalInterface会强制检查interface是否只有一个abstract方法,若interface存在多个abstract方法将会提升错误。

lambda表达式仅支持包含一个abstract方法的interface。

举个栗子–自定义一个函数编程风格的接口

  • 普通接口写法
public interface Task <IN>{

    void get(IN input);
}
  • 使用@FunctionalInterface注解
@FunctionalInterface
public interface Task2 <IN>{

    void get(IN input);
}
  • 普通接口、@FunctionalInterface两种写法的单元测试及运行结果:
@SpringBootTest
@RunWith(SpringRunner.class)
public class Demo2Test {

    @Test
    public void taskTest() {
        this.testTask(input -> {
            System.out.println("hello, " + input);
        }, "task");
        this.testTask2(input -> {
            System.out.println("hi, " + input);
        }, "task2");
    }

    private <IN> void testTask(Task<IN> task, IN input) {
        System.out.println("execute task");
        task.execute(input);
    }

    public <IN> void testTask2(Task2<IN> task, IN input) {
        System.out.println("execute task2");
        task.execute(input);
    }

}

执行结果:

execute task
hello, task
execute task2
hi, task2

上述两种方式的代码运行结果完全一样

  • 使用@FunctionalInterface注解修饰包含两个及以上的abstract方法的interface,如下这个写法,代码编译不通过,IDE中代码检查会直接提升Multiple non-overriding abstract methods found in interface
@FunctionalInterface
public interface Task <IN, OUT>{

    OUT get(IN input);
    
    void get();
}

3 使用案例

lambda表达式在jdk8中有着丰富的使用案例,如流处理工具类Stream其中就大量的使用的lambda表达式。基本包含如下四种类型:

3.1 Supplier

只有返回值,没有入参

@FunctionalInterface
public interface Supplier<T> {
    
    T get();
}

Stream中的list.stream().collect()方法的入参使用的就是Supplier类型。

3.2 Consumer

只有入参,没有返回值

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);
}

Stream中的list.stream().forEach()方法的入参使用的就是Consumer类型。

3.3 Predicate

有入参,返回值是boolean类型

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}

Stream中的list.stream().filter()方法的入参使用的就是Predicate类型。

3.4 Funcation

既有入参、又有返回值

@FunctionalInterface
public interface Funcation<T, R> {

    R accept(T t);
}

Stream中的list.stream().map()方法的入参使用的就是Funcation类型。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值