探索 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。这些操作是惰性的,只有在终止操作执行时才会实际处理数据。常见的中间操作有 filter、map、sorted、distinct、limit 和 skip。

示例:
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 的处理,并生成一个结果。常见的终止操作有 forEach、collect、reduce、count、findFirst、findAny 和 allMatch 等。

示例:
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。

相关推荐
学长毕设3 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
zzu123zsw4 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
源码集结号5 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场5 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
啃瓜子的松鼠6 小时前
泛微OAe9-后端二开异步调用
java
秋天的怀念_David7 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
外收内放7 小时前
Python基础语法练习题(73)
java·前端·python
Wang's Blog7 小时前
Java 项目实战: 交友项目 - 环信后台发送消息测试
java·交友
用户3721574261357 小时前
Java 操作 Word 脚注和尾注:添加、读取与删除
java
小嘉丶学长8 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节