Java8 Lambda 介绍

简介: Lambda是一段可以传递的代码,可以被多次执行。当然,不使用Lambda表达式也可以写出同样的代码,对比如下,可以看到lambda的写法简洁很多。 public interface Invocable { R invoke(T input); } public static void main(String[] args) {

Lambda是一段可以传递的代码,可以被多次执行。当然,不使用Lambda表达式也可以写出同样的代码,对比如下,可以看到lambda的写法简洁很多。

public interface Invocable<T,R> {
    R invoke(T input);
}

public static void main(String[] args) {
    myInvoke("str", new Invocable<String, String>() {
        @Override
        public String invoke(String input) {
            return "MyInvocable#invoke --> " + input;
        }
    });

    myInvoke("str", (input) -> "MyInvocable#invoke --> " + input);
}

private static void myInvoke(String str, Invocable invocable) {
    System.out.println(invocable.invoke(str));
}

Lambda语法

Lambda语法格式如下,如果一个表达式无法完整表达逻辑,那就就写成一个代码块,用花括号括起。

(参数...) -> [表达式;代码块]

示例:

    //表达式
    (String first, String second) -> Integer.compare(first.length(), second.length());
    //代码块
    (String first, String second) -> {
        if (first.length() < second.length()) return -1;
        else if (first.length() > second.length()) return 1;
        else return 0;
    }
    //无入参
    () -> {
        for (int i = 0; i < 10; i++) doSomeThing();
    }
    //自动推导入参类型
    Comparator comp = (first, second) -> Integer.compare(first.length(), second.length());

函数式接口

对于只包含一个抽象方法的接口,就可以通过lambda表达式来创建该接口的对象啦,这种接口就叫做函数式接口。java.util.function包中预定义了好多函数式接口,并且同意标记上了注解【@FunctionalInterface】。自定义的函数式接口也建议加上这个注解,因为编译器会检查该实体,是否只包含一个抽象方法的,同时也更加清晰可读。
例如:

    Map<Integer, User> userMap = Stream.of(new User(0, "张三", 18, 0), new User(0, "张四", 19, 0), new User(0, "老张", 20, 1))
            .collect(Collectors.toMap(User::getId, item -> item));

这里的toMap方法接收的输入参数就是Function函数:

public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper) {

其他常见预定义函数的说明可以参见上一篇文章(http://www.atatech.org/articles/61907

方法引用和构造器引用

方法引用:

    //对象::实例方法:
    instance::method --> (input1,input2...) -> instance.method(input1,input2...)

    //类::静态方法:
    class::staticMethod --> (input1,input2...) -> class.staticMethod(input1,input2...)

    //类::实例方法:
    class::method --> (input1,input2,input3...) -> input1.method(input2,input3...)

构造器引用:

    
    List<String> list = Arrays.asList("a", "b");
    list.stream().map(MyClass::new);

构造器引用会自动适配一个合适的构造函数,例如上面的示例会适配一个入参为一个String类型的构造函数。

Lambda的闭包语法糖

在java中原有的闭包:

public static Supplier<Integer> testClosure() {
    final int i = 1;
    return new Supplier<Integer>() {
        @Override
        public Integer get() {
            return i;
        }
    };
}

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

此处变量i是testClosure方法的内部变量,但是我们在匿名内部函数get中却返回了 i;内部变量 i 的生存周期延长了,并且使得变量 i 可以被外部函数所引用,这就是闭包。注意变量 i 必须为final,否则会编译错误。

在Lambda中的闭包:

public static Supplier<Integer> testClosure() {
    int i = 1;
    //i++;
    return () -> {
        return i;
    };
}

此处 i 不需要定义为final,但是这仅仅是一个语法糖,事实上任何对 i 的value的变更一样会引起语法错误。

延迟执行

lambda表达式都是延迟执行的,如果需要立即执行一段代码,就没必要使用lambda表达式了,就好像如果需要立即执行就没必要使用匿名内部类一样。lambda表达式可以在另一个线程中执行,可以多次运行,按需运行,在某个正确的时机(事件触发,算法运行的某个时间点)运行。

例如,常用的log记录方式如下:

    log.info("x:" + x + ",y:" + y);

参数会立即计算完成再传递给info方法,此时会判断日志级别,如果符合info输出才会打印日志,如果为debug等info不输出的情况,会忽略当前信息,但是呢参数已经计算过了。做了一次无用功。此时如果改为lambda延迟执行,则不会出现这种无谓的计算。如下:

    log.info(() -> "x:" + x + ",y:" + y);

总结

迟来的特性,哈哈,不过还是带来了很多便利的。

目录
相关文章
|
17天前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
20天前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
24天前
|
Java API 开发者
Java中的Lambda表达式与函数式编程####
在Java的演变过程中,Lambda表达式和函数式编程的引入无疑是一次重大的飞跃。本文将深入探讨Lambda表达式的定义、用法及优势,并结合实例说明如何在Java中利用Lambda表达式进行函数式编程。通过对比传统编程方式,揭示Lambda表达式如何简化代码、提高开发效率和可维护性。 ####
|
4天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
17 0
|
1月前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
2月前
|
Java API
[Java]Lambda表达式
本文主要介绍了Java中的Lambda表达式,包括其优化匿名内部类的方式、使用规范、内置函数式接口及方法引用等内容。文章详细解析了Lambda的基础语法、参数列表、方法体的简化规则,以及如何利用Lambda优化代码。此外,还探讨了Lambda的作用域和引用规则,强调了对局部变量、成员变量和常量的访问限制,旨在帮助读者全面理解和掌握Lambda表达式的应用。
20 0
[Java]Lambda表达式
|
2月前
|
Java 程序员 API
Java中的Lambda表达式:简化代码的秘密武器
【10月更文挑战第11天】 在Java编程中,Lambda表达式是一种简洁而强大的工具,它允许我们将函数作为参数传递给其他方法。本文将介绍Lambda表达式的基本概念、使用方法以及在实际项目中的应用案例,帮助你更好地理解和利用这一特性来简化代码。
24 8
|
2月前
|
Java 测试技术 开发者
🌟Java零基础-Lambda运算符详解 🌟
【10月更文挑战第12天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
23 1
|
2月前
|
并行计算 Java API
Java中的Lambda表达式及其应用
本文将深入探讨Java中的Lambda表达式,从基本概念到实际应用。我们将了解Lambda表达式的定义、优势和使用场景,并通过实例展示其在Java编程中的强大功能。无论是初学者还是经验丰富的开发者,都可以从中获得有价值的见解。
|
2月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
27 1