【Java8新特性】- Lambda表达式

简介: Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

Java8新特性 - Lambda表达式

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!

lambda表达式.jpg

简介

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。这是来自百度百科对lambda的介绍,实际上lambda就是简化了匿名函数的编写,只需一行代码就能代替繁杂的代码。
lambda主要是可以非常简洁的形式调用我们的匿名函数接口。

简单例子

首先声明一个接口,并且编写实现类实现这个接口

// UserService
public interface UserService {
    void add();
}
// UserServiceImpl
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("UserServiceImpl --- add");
    }
}

一般来说是通过new实现类从而拿到实现中的add方法,如果通过new接口类就需要使用匿名内部类的形式调用接口。IDEA会提示使用lambda表达式。
image.png

如下代码可以看一下对比。

public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    userService.add();

    UserService user = new UserService() {
        @Override
        public void add() {
            // 匿名内部接口业务逻辑
            System.out.println("匿名内部接口业务逻辑");
        }
    };

    // Lamdba表达式
    UserService user2 = () -> System.out.println("匿名内部接口业务逻辑");
    user2.add();
}

Lambda表达式的规范

Java中的Lambda表达式的规范,必须是为函数接口。

使用函数式接口

使用Lambda表达式依赖于函数式接口:
1、使用@FunctionalInterface注解来声明函数接口
2、在这个函数接口中只能有一个抽象方法
3、在函数接口中可以定义object类中的方法
4、可以有静态方法
*函数式接口(Functional Interface) 就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
更多函数式接口可以查看菜鸟联盟https://www.runoob.com/java/java8-functional-interfaces.html

函数式接口的定义

通过@FunctionalInterface注解声明接口类,在java中也有许多内置的函数接口,详情看菜鸟联盟。

@FunctionalInterface // 声明函数式接口
public interface UserService {
    void add();

    String toString(); // Object类中的方法

    static void hello() { // 静态方法
        System.out.println("hello");
    }
}

Lambda表达式的基础语法

表达式格式

(参数) -> {方法体}

格式说明

():存放参数,留空就代表没有参数。函数接口的参数列表,不需要写类型,需要定义参数名称。
->:是新引入的语法格式,代表指向动作。
{}:方法体

无参方法调用

在接口类中声明一个无参的抽象方法,通过lambda表达式来完成调用。()不需要存放参数,最后将会返回一个实现类对象。在通过调用对象的get方法。

// 匿名内部接口业务逻辑
UserService user2 = () -> System.out.println("匿名内部接口业务逻辑");
user2.get();

更加简便的写法

((UserService)() -> System.out.println("匿名内部接口业务逻辑")).get();

含参数方法调用

在MathService定义一个含有参数的抽象方法,原本的方式通过匿名内部接口。可以通过使用lambda表达式更加简便,并且可以省去{},也不需要return。

MathService math = new MathService() {
    @Override
    public Integer add(int a, int b) {
        return a + b;
    }
};

MathService mathService = (a, b) -> a + b;

System.out.println(mathService.add(1, 1));

方法引入

规则

方法引入需要遵循规范:方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。
方法引入的规则:
       静态方法引入: 类名::(静态)方法名称
       对象方法引入: 类名:: 实例方法名称
       实例方法引入:new对象 对象实例::方法引入
       构造函数引入:类名::new
方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。
1664976332232.png

实例

构造器引用

通过构造器引用实例化对象,

public static void main(String[] args) {
    // 使用匿名内部类
    CarService carService = new CarService() {
        @Override
        public Car getCar() {
            return null;
        }
    };
    // 使用引用方法
    CarService car = Car::new;
    car.getCar();
}
public class Car {
    private String name;
    private String brand;

    public Car() {
    }
}
public interface CarService {
    Car getCar();
}

静态方法引入

UserService u = UserService::hello;
u.get();

在userservice中,有一个抽象get方法和一个静态方法

@FunctionalInterface
public interface UserService {
    void get();
    static void hello() {
        System.out.println("hello");
    }
}

运行后会输出hello

hello

Process finished with exit code 0

对象方法引入

这是一种更为方便的写法, 我记得在mybatis-plus使用自带条件查询的时候会用到这种方式,以下用简单例子来实现。java8中提供了public interface Function<T, R>的类,这个类也是使用@FunctionalInterface注解,可见也是函数式接口。
代码:

// 在car中声明一个方法
public class Car {
    public String Info() {
        return "保时捷 - 帕拉梅拉";
    }
}
// 函数式接口
@FunctionalInterface
public interface CarInFoService {
    String getCar(Car car);
}

测试采用了三种方式进行比较

public class LambdaTest4 {
    public static void main(String[] args) {
        System.out.println("**************匿名内部类**************");
        CarInFoService carInFoService = new CarInFoService() {
            @Override
            public String getCar(Car car) {
                return car.Info();
            }
        };
        System.out.println(carInFoService.getCar(new Car()));
        System.out.println("**************lambda**************");
        CarInFoService carInFoService2 = (car) -> car.Info();
        System.out.println(carInFoService2.getCar(new Car()));
        System.out.println("**************对象方法引入**************");
        CarInFoService carInFoService3 = Car::Info;
        System.out.println(carInFoService3.getCar(new Car()));

        // R apply(T t); T  apply方法传递的参数类型 : R apply 方法返回的类型
        Function<String, Integer> function = String::length;
        System.out.println(function.apply("lyd_code"));
    }
}

结果
image.png

Lambda表达式遍历

通过foreach循环遍历,forEach实际上需要使用匿名内部类Consumer<? super E>。
image.png
代码如下

public class LambdaTest5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("lyd");
        list.add("tom");
        list.add("jack");
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("name: " + s);
            }
        });
        System.out.println("lambda表达式");
        /**
         * s:遍历链表所得到的元素字符串
         */
        list.forEach(s -> System.out.println("name: " + s));
    }
}

测试结果
image.png

Lambda排序

通过Comparator匿名内部类

public class LambdaTest6 {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("lyd", 99));
        students.add(new Student("lkj", 55));
        students.add(new Student("llm", 67));
        students.add(new Student("lss", 87));

//        students.sort(new Comparator<Student>() {
//            @Override
//            public int compare(Student o1, Student o2) {
//                return o1.getScore() - o2.getScore();
//            }
//        });

        students.sort((o1, o2) -> o1.getScore() - o2.getScore());

        students.forEach(student -> System.out.println("name: " + student.getName() + " score: " + student.getScore()));
    }
}

结果
image.png

为了写好博客,包括代码、文字,我是经过斟酌了的,如果有错误,欢迎指正!感谢观看!
👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍

相关文章
|
12天前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
21天前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
36 6
|
21天前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
23天前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
20天前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
23天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
25 0
|
7天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
37 6
|
22天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
20天前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
下一篇
DataWorks