首页 > 编程语言 >Java 8 新特性:Lambda 表达式、方法引用和 Stream 流

Java 8 新特性:Lambda 表达式、方法引用和 Stream 流

时间:2024-04-01 14:45:14浏览次数:14  
标签:Java Stream employees 接口 Employee new id Lambda

函数式接口

具有单个抽象方法的接口被称为“函数式接口”,函数式接口的实例被称为“函数对象”,表示函数和要采取的动作

六大基础函数式接口:

函数式接口 名称 用途 方法
Consumer<T> 消费型接口 操作类型 T 的对象 void accept(T t)
Supplier<T> 供给型接口 返回类型为 T 的对象 T get()
Function<T, R> 函数型接口 操作类型为 T 的对象,返回类型为 R 的对象 R apply(T t)
Preicate<T> 判断型接口 判断类型为 T 的对象是否满足约束,并返回 boolean 值 boolean test(T t)
unaryOperator<T> 一元运算接口 操作类型为 T 的对象,返回类型为 T 的对象。常见的操作有:自增、自减和按位取反等 T apply(T t)
BinaryOperator<T, T> 二元运算接口 操作两个类型为 T 的对象,返回类型为 T 的对象。常见的操作有:两数相加和两数相减等 T apply(T t1, T t2)

注意:Function 接口参数和返回值不一致,Operator 接口参数和返回值一致。

java.util.Function 包中共有 43 个接口,很多接口都是上述基础接口派生而来的,例如,BiConsumer(T, U)BiFunction<T, U, R> 等。

Lambda 表达式

创建函数式接口的实例可以用 Lambda 表达式创建。

Lambda 表达式的语法总结:

  • -> 的左边是形参列表,参数类型可以省略,形参只有一个,() 也可以省略。
  • -> 的右边是 Lambda 体,如果只有一条语句,{} 可以省略,return 关键字也可以省略。

Lambda 表达式的一些示例:

Consumer<Integer> consumer = a -> System.out.println(a);

Supplier<String> supplier = () -> "hello world!";

Function<String, Integer> function = a -> a.length();

Predicate<String> predicate = a -> a.length() > 2;

Comparator<Integer> comparator = (a, b) -> Integer.compare(b, a);

方法引用

方法引用是基于 Lambda 的进一步刻画。格式:类(或对象):: 方法,有三种情况。

首先,准备 Employee 类:

public class Employee {
    private int id;
    private String name;
    private int age;
    private double salary;

	public Employee(int id) {
		this.id = id;
	}

	public Employee(int id, String name) {
	    this.id = id;
	    this.name = name;
	}

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
}

情况一:对象 :: 非静态方法

函数式接口中的抽象方法 a 和实现 a 时调用的对象方法 b 的参数列表和返回值类型都相同。该方法是非静态方法,需要对象调用。

例如:

Employee emp = new Employee(1000, "Tom", 22, 11000.0);
Supplier<String> supplier1 = new Supplier<String>() {
	@Override
	public String get() {
		return emp.getName();
	}
};
Supplier<String> supplier2 = () -> emp.getName(); // Lambda 表达式
Supplier<String> supplier3 = emp::getName; // 方法引用

以上三种实现 Suppler 接口的方式等效。

再例如,根据字符串的长度对字符串 List 进行排序,代码如下:

List<String> words = Arrays.asList("abd", "ab", "ac");
words.sort(new Comparator<String>() {
	@Override
	public int compare(String a, String b) {
		return a.length() - b.length();
	}
});

上述代码可以简化为:

words.sort(words, (a,b) -> a.length() - b.length);

还可以简化为:

words.sort(Comparator.comparingInt(String::length));

情况二:类 :: 静态方法

函数式接口中的抽象方法 a 和实现 a 时调用的类静态方法 b 的参数列表和返回值类型都相同。该方法是非静态方法,需要对象调用。

例如:

Comparator<Integer> comparator1 = (a, b) -> Integer.compare(a, b);
Comparator<Integer> comparator2 = Integer::compare;

情况三:类 :: 非静态方法

函数式接口中的抽象方法 a 与其内部实现时调用的对象的某个方法 b 的返回值相同。同时,抽象方法 a 有 n 个参数,方法 b 有 n - 1 个参数,a 的第一个参数是方法 b 的调用者。

例如:

Comparator<Integer> comparator1 = (a, b) -> a.compareTo(b);
Comparator<Integer> comparator2 = Integer::compareTo;

情况四:构造器引用

构造器引用格式:类名 :: new。具体调用类中的哪一个构造器取决于函数式接口中的抽象方法的形参列表。

例如:

Function<Integer, Employee> function1 = (id) -> new Employee(id);
Function<Integer, Employee> function2 = Employee::new;

再例如:

BiFunction<Integer, String, Employee> biFunction1 = (id, name) -> new Employee(id, name);
BiFunction<Integer, String, Employee> biFunction2 = Employee::new;

构造器引用的数组形式:

Function<Integer, Employee[]> func1 = (a) -> new Employee[a];
Function<Integer, Employee[]> func2 = Employee[]::new;

Stream 流

Stream 是 Java 8 中处理集合的关键抽象概念,使用 Stream API 对几何数据进行操作,就类似于使用 SQL 执行的数据库查询。Stream 是数据渠道,用于操作数据集合。

注意:

  • Stream 不会自己存储数据。
  • Stream 不会改变原数据。它们会返回一个持有结果的新 Stream。
  • Stream 一旦终止操作就不能再调用其它中间操作了。

Stream 操作的三个步骤:

  1. 创建 Stream。
  2. 中间操作,例如排序、查找、过滤、映射、遍历等。
  3. 终止操作。

创建 Stream

准备数据:

List<Employee> employees = new ArrayList<>();
Employee emp1 = new Employee(1, "Tom", 23, 4500.0);
employees.add(emp1);
Employee emp2 = new Employee(2, "Mary", 26, 6500.0);
employees.add(emp2);
employees.add(new Employee(3, "Jerry", 19, 3500.0));
employees.add(new Employee(4, "Nancy", 35, 11000));

创建 Stream 有三种方式:

  • 方式一:通过集合获取 Stream。
  • 方式二:通过数组获取 Stream。
  • 方式三:Stream.of(T... values) 方法。

例如:

// 方式一:通过集合获取 Stream
Stream<Employee> stream = employees.stream();
// 方式二:通过数组获取 Stream
IntStream intStream = Arrays.stream(new int[]{1, 2, 3, 4, 5});
// 方式三:Stream.of(T... values) 方法
Stream<Employee> employeeStream = Stream.of(emp1, emp2);

中间操作

常用的方法如下:

  • filter(Predicate<? super T> predicate):过滤。
  • <R> Stream<R> map(Function<? super T, ? extends R> mapper):映射。
  • Stream<T> limit(long maxSize):截断前 n 个元素。
  • Stream<T> skip(long n):跳过前 n 个元素。
  • distinct():根据对象的 hashcode()equals() 方法去重。
  • Stream<T> sorted(Comparator<? super T> comparator):排序。

示例代码:

// 查询集合中员工薪资大于 7000 的员工信息
employees.stream().filter(a -> a.getSalary() > 7000).forEach(System.out::println);
// 查询集合中员工薪资大于 7000 的员工的 id
employees.stream().filter(a -> a.getName().length() > 3).map(Employee::getId).forEach(System.out::println);
// 只取前 2 项
employees.stream().limit(2).forEach(System.out::println);
// 跳过前 2 项
employees.stream().skip(2).forEach(System.out::println);
// 去重
employees.stream().distinct().forEach(System.out::println);
// 根据 employee 名字的长度排序
employees.stream().sorted(Comparator.comparingInt(a -> a.getName().length())).forEach(System.out::println);

终止操作

终止操作分为三种:

  • 匹配与查找。
  • 规约。
  • 收集。

匹配与查找

方法:
anyMatch():是否有一个匹配。
allMatch():是否全部匹配。
findFirst():查找第一个。
count():计数。
max():最大值。
min():最小值。
forEach():遍历。

例如:

// 是否有员工的薪资大于 7000
employees.stream().anyMatch(employee -> employee.getSalary() > 7000);
// 是否所有员工的年龄都大于 20
employees.stream().allMatch(employee -> employee.getAge() > 20);
// 年龄最大的员工的名字
employees.stream().max(Comparator.comparingInt(Employee::getAge)).get().getName();
// 遍历打印所有员工的信息
employees.forEach(System.out::println);

规约

Optional<T> reduce(BinaryOperator<T> accumulator) 将值反复结合起来得到一个值。

例如:

// 计算所有员工薪资的总和
Double sum = employees.stream().map(Employee::getSalary).reduce(Double::sum).get();

收集

collect(Collectors.toList):将结果收集起来转成 List。

例如,int[] 数组转成 List<Integer> 集合:

int[] arr = new int[]{1, 2, 3, 4, 5};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

标签:Java,Stream,employees,接口,Employee,new,id,Lambda
From: https://www.cnblogs.com/code-qin/p/18108374

相关文章

  • Java:异常处理
    在Java中,异常是程序运行时发生的不正常情况,它们打断了正常的指令流。异常处理是Java语言的一个重要特性,它可以帮助程序员捕获并处理运行时可能出现的错误,从而提高程序的健壮性。以下是Java中异常相关的详细知识:异常类的层次结构Java的异常类都继承自java.lang.Throwable类......
  • lambda表达式
    lambda表达式c++98中的一个例子在c++98中如果想要对一个数据集合中的元素进行排序。可以使用std::sort方法。#include<algorithm>#include<functional>intmain(){intarray[]={4,1,8,5,3,7,0,9,2,6};//默认按照小于比较,排出来的结果是升序的std::sort(arra......
  • 身份证实名认证接口会返回什么?javascript身份核验接口示例
    身份证实名认证接口是通过核验身份证号、姓名、证件头像等一系列的要素信息进行用户身份验证,那么,身份证实名认证接口一般在核验完成后会返回什么参数信息呢?下面翔云API小编为大家答疑解惑!一般情况下,身份核验只会返回一致或者不一致的结果,不一致的情况下会返回那些参数不一致,以翔......
  • 【附源码】JAVA计算机毕业设计智慧外贸平台(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在全球经济一体化的时代背景下,智慧外贸平台的建设已成为提升我国外贸竞争力、优化国际贸易环境的关键一环。随着信息技术的迅猛发展,传统的外贸模式已......
  • 【附源码】JAVA计算机毕业设计智慧物流管理系统(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息化时代的快速发展,物流行业作为现代经济体系的重要支柱,正面临着前所未有的机遇与挑战。传统的物流管理方式已难以适应现代社会的需求,智能化、......
  • 【附源码】JAVA计算机毕业设计智慧小饭桌(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着社会的快速发展和科技的进步,人们对教育的关注和要求也在不断提高。在当今快节奏的生活中,许多家庭面临着孩子午餐难以解决的问题,尤其是对于那些工......
  • 【附源码】JAVA计算机毕业设计智慧型居民小区物业管理(springboot+mysql+开题+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速和居民生活水平的提高,智慧型居民小区逐渐成为现代城市发展的一个重要方向。在这样的背景下,传统物业管理模式已难以满足居民日益......
  • Android Binder——Java层介绍(三)
    一、简介       对于Android系统,一般是从java层到native层,再到kernel驱动层,形成一个完整的软件架构。Android系统中的BinderIPC通信机制的整体架构也是如此,Java和C++层都定义有同样功能的供应用程序使用的Binder接口。然而Java层中Framework层的......
  • Java从萌新小白到顶级大牛(4更新中)
    自定义异常Java标准库定义的常用异常包括:Exception│├─RuntimeException│ ││ ├─NullPointerException│ ││ ├─IndexOutOfBoundsException│ ││ ├─SecurityException│ ││ └─IllegalArgumentException│    ││ ......
  • JavaWeb学习笔记——第十一天
    SpringBootWeb案例(二)新增员工实现EmpController:@PostMappingpublicResultadd(@RequestBodyEmpemp){log.info("新增员工:{}",emp);empService.add(emp);returnResult.success();}EmpService:voidadd(Empemp);EmpServiceImpl:@Overri......