Java8-Lambda表达式

本文详细介绍了Java 8中的Lambda表达式,包括其基本语法、使用场景和与函数式接口的关系。Lambda表达式简化了代码,使得匿名函数的编写更加简洁。文章还列举了几个内置的函数式接口,如Consumer、Supplier和Function,并通过实例展示了它们的使用。此外,还讲解了方法引用的概念,以及如何通过方法引用创建Lambda表达式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Lambda表达式简介

Lambda表达式(也称闭包),可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。Lambda表达式可以简化函数式接口的使用。函数式接口就是一个只有一个抽象方法的普通接口,像这样的接口就可以使用Lambda表达式来简化代码的编写。

2、Lambda的基本语法

(parameters) -> expression;
或者
(parameters) -> { statements; }
    箭头(->)操作符将 Lambda 表达式拆分成两部分:
    左侧(parameters)Lambda 表达式的参数列表
    右侧:Lambda 表达式中所需实现的功能, 即 Lambda

注意:

  • 可选参数类型声明: 不需要声明参数类型,编译器可以统一识别参数值
  • 可选的参数圆括号: 一个参数无需定义圆括号,但多个参数需要定义圆括号
  • 可选的Lambda体大括号:如果主体包含了一个语句,就不需要使用大括号
  • 可选的返回关键字: 如果Lambda体不加{ }就不用写return,Lambda体加上{ }就需要添加return。
@Test
public void lambdaTest(){
    Integer num = (int) (Math.random() * 100);
    functionInterface<Integer> functionInterface = x -> x > 5? "good" :"bad";
    String test = functionInterface.functionTest(num);
    System.out.println(num + " is " + test);
}
interface functionInterface<T>{
    String functionTest(T t);
}

3、Lambda的适用场景

Lambda表达式只适用于函数式接口,即接口有且只有一个抽象方法。

函数式接口

  • 有且只有一个抽象方法的接口被为函数式接口
  • 接口现在还可以拥有默认方法(即在类没有对方法进行实现时,其主体为方法提供默认实现的方法)。哪怕有很多默认方法,只要接口只定义了一个抽象方法,它就仍然是一个函数式接口
  • 函数式接口可以显式的被@FunctionalInterface所表示,当被标识的接口不满足规定时,编译器会提示报错,注意@FunctionalInterface不是必需的,但对于为此设计的接口而言,使用它是比较好的做法

4、 Java8内置的函数式接口

Java 8的库设计师帮你在java.util.function包中引入了几个新的函数式接口。例如:Predicate、Consumer和Function

接口参数返回值
Consumer(消费型接口)Tvoid
Supplier(供给型接口)noneT
Function(函数型接口)TR
Predicate(断言型接口)Tboolean

java.util.function.Consumer < T > 接口定义了一个名叫accept的抽象方法,它接受泛型T对象,无返回值,重点在于内部消费.

    @Test
    public void test1(){
        //消费型 Consumer 接口只有一个抽象方法 accept,参数列表只有一个泛型t,无返回值,重点在于内部消费
        consumerTest("good", System.out::println);
    }
    public void consumerTest(String str, Consumer<String> consumer){
        consumer.accept(str);
    }

java.util.function.Supplier< T > 接口定义了一个名叫get的抽象方法,参数列表为空,有返回值,返回值得数据类型为T

@Test
public void test2(){
    //供给型 Supplier 只有一个抽象方法 get,参数列表为空,有返回值,返回值得数据类型为T。
    List<Integer> integers = supplierTest(5, () -> (int) (Math.random() * 100));
    integers.forEach(System.out::println);
}
public List<Integer> supplierTest(Integer num, Supplier<Integer> supplier){
    Integer[] arr = new Integer[num];
    for (int i = 0; i < num; i++) {
        arr[i] = supplier.get();
    }
    return Arrays.asList(arr);
}

java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。如果你需要定义一个Lambda,将输入对象的信息映射到输出,就可以使用这个接口

@Test
public void test3(){
    //函数型 Function<T, R> 只有一个抽象方法名为 apply,参数列表只有一个参数为T,有返回值,返回值的数据类型为R。
    String test = functionTest("Hello Mr.Zhu", String::toUpperCase);
    System.out.println(test);
}

public String functionTest(String str,Function<String,String> function){
    return function.apply(str);
}

java.util.function.Predicate< T >接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。需要表示一个涉及类型T的布尔表达式时,就可以使用这个接口。

@Test
public void test4(){
    //断言型 又名判断型。 Predicate 只有一个抽象方法 test,参数列表只有一个参数为 T,有返回值,返回值类型为 boolean。
    boolean test = predicateTest((int) (Math.random() * 100), x -> {
        System.out.println(x);
        return x > 50 ? true : false;
    });
    System.out.println(test);
}
public boolean predicateTest(Integer num , Predicate<Integer> predicate){
    return predicate.test(num);
}

5、方法引用

方法引用是用来直接访问类或者实例已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。

方法引用可以被看作仅仅调用特定方法的Lambda的一种快捷写法。它的基本思想是,如果一个Lambda代表的只是“直接调用这个方法”,那最好还是用名称来调用它,而不是去描述如何调用它。事实上,方法引用就是让你根据已有的方法实现来创建Lambda表达式。但是,显式地指明方法的名称,你的代码的可读性会更好

5.1、如何构建方法引用

使用::操作符将方法名和对象或类的名字分隔开。::是域操作符(也可以称作定界符、分隔符。

方法引用主要有三类。
在这里插入图片描述

  1. 指向静态方法的方法引用(例如Integer的parseInt方法,写作Integer::parseInt)
  2. 指向任意类型实例方法的方法引用(例如String的length方法,写作String::length)。引用一个对象的方法,而这个对象本身是Lambda的一个参数。例如,Lambda表达式(String s)-> s.toUppeCase()可以写作String::toUpperCase。
  3. 指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensive-Transaction::getValue)。

5.2、构造函数引用

对于一个现有构造函数,你可以利用它的名称和关键字new来创建它的一个引用:ClassName::new

	@Test
    public void test(){
        Function<String, Person> function = Person::new // 等同于 Function<String,Person> function1 = (String s) -> new Person(s);
        Person person = function.apply("thinkwon");
        // doge
        System.out.println(person.getName());
    }
 	class Person {
        private final String name;
        public Person(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值