探索 Java 8 中的 Stream API

探索 Java 8 中的 Stream API

Java 8 引入了 Stream API,极大地简化了对集合(如 List、Set)的操作。Stream 提供了一种声明式的方式来处理数据,允许我们使用类似 SQL 的操作来操作集合。本文将详细介绍 Java 中的 Stream API,包括创建 Stream、常用操作符、终止操作以及实际使用示例。

1. 什么是 Stream?

Stream 是一个用于处理数据序列的抽象概念。它不存储数据,而是从数据源(如集合、数组等)按需生成数据。Stream 提供了一套丰富的操作符,可以链式调用,以一种声明式的方式处理数据。

2. 创建 Stream

Stream 可以从多种数据源创建,最常见的是从集合和数组创建。

java 复制代码
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamExample {
    public static void main(String[] args) {
        // 从集合创建 Stream
        List<String> list = Arrays.asList("a", "b", "c");
        Stream<String> streamFromList = list.stream();

        // 从数组创建 Stream
        String[] array = {"x", "y", "z"};
        Stream<String> streamFromArray = Arrays.stream(array);

        // 使用 Stream.of 创建 Stream
        Stream<String> streamOf = Stream.of("1", "2", "3");
    }
}

3. 中间操作

中间操作用于转换 Stream,返回一个新的 Stream。这些操作是惰性的,只有在终止操作执行时才会实际处理数据。常见的中间操作有 filtermapsorteddistinctlimitskip

示例:
java 复制代码
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class IntermediateOperations {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 过滤偶数
        List<Integer> evenNumbers = numbers.stream()
            .filter(n -> n % 2 == 0)
            .collect(Collectors.toList());

        // 将每个数平方
        List<Integer> squares = numbers.stream()
            .map(n -> n * n)
            .collect(Collectors.toList());

        // 排序
        List<Integer> sortedNumbers = numbers.stream()
            .sorted()
            .collect(Collectors.toList());

        // 去重
        List<Integer> distinctNumbers = numbers.stream()
            .distinct()
            .collect(Collectors.toList());

        System.out.println("Even numbers: " + evenNumbers);
        System.out.println("Squares: " + squares);
        System.out.println("Sorted numbers: " + sortedNumbers);
        System.out.println("Distinct numbers: " + distinctNumbers);
    }
}

4. 终止操作

终止操作用于触发 Stream 的处理,并生成一个结果。常见的终止操作有 forEachcollectreducecountfindFirstfindAnyallMatch 等。

示例:
java 复制代码
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class TerminalOperations {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // forEach 打印每个元素
        numbers.stream()
            .forEach(System.out::println);

        // collect 收集结果为 List
        List<Integer> collectedNumbers = numbers.stream()
            .collect(Collectors.toList());

        // reduce 求和
        Optional<Integer> sum = numbers.stream()
            .reduce((a, b) -> a + b);

        // count 统计数量
        long count = numbers.stream()
            .count();

        // findFirst 找到第一个元素
        Optional<Integer> first = numbers.stream()
            .findFirst();

        // allMatch 判断是否所有元素都大于 0
        boolean allGreaterThanZero = numbers.stream()
            .allMatch(n -> n > 0);

        System.out.println("Collected numbers: " + collectedNumbers);
        sum.ifPresent(s -> System.out.println("Sum: " + s));
        System.out.println("Count: " + count);
        first.ifPresent(f -> System.out.println("First: " + f));
        System.out.println("All greater than zero: " + allGreaterThanZero);
    }
}

5. 实际示例

假设我们有一个 Employee 类,并希望通过 Stream API 处理一组员工数据。

java 复制代码
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

class Employee {
    private String name;
    private double salary;

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

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }

    @Override
    public String toString() {
        return name + ": " + salary;
    }
}

public class EmployeeExample {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("Alice", 70000),
            new Employee("Bob", 80000),
            new Employee("Charlie", 90000),
            new Employee("David", 60000)
        );

        // 找到薪水最高的员工
        Optional<Employee> highestPaidEmployee = employees.stream()
            .max(Comparator.comparingDouble(Employee::getSalary));

        highestPaidEmployee.ifPresent(emp -> System.out.println("Highest Paid Employee: " + emp));

        // 找到所有薪水大于 65000 的员工
        List<Employee> highEarners = employees.stream()
            .filter(e -> e.getSalary() > 65000)
            .collect(Collectors.toList());

        System.out.println("High earners: " + highEarners);

        // 计算所有员工的总薪水
        double totalSalary = employees.stream()
            .mapToDouble(Employee::getSalary)
            .sum();

        System.out.println("Total salary: " + totalSalary);
    }
}

6. 总结

Stream API 是 Java 8 引入的强大工具,提供了一种声明式、链式调用的方式来处理数据。通过了解中间操作和终止操作,你可以高效地处理数据流,简化代码,提高可读性和可维护性。希望本文能帮助你更好地理解和使用 Java 中的 Stream API。

相关推荐
九圣残炎20 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge23 分钟前
Netty篇(入门编程)
java·linux·服务器
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐1 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野1 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq04151 小时前
J2EE平台
java·java-ee
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee