探索 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。

相关推荐
xlsw_3 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白665 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp5 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶5 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb