一、Stream 流的概念

Stream 是 Java 8 引入的一个用于简化集合、数组等数据处理操作的 API。 它支持函数式编程风格,可以通过链式调用完成筛选、排序、映射、聚合等复杂操作,从而减少冗余代码。

二、Stream 流的获取方式

集合或数组如何转化为 Stream 流对象:

来源 获取方式 示例
List 集合 list.stream() Stream<String> s = list.stream();
Set 集合 set.stream() Stream<Integer> s = set.stream();
Map 集合 通过键、值或键值对获取流 map.keySet().stream() map.values().stream() map.entrySet().stream()
数组 Arrays.stream(array)Stream.of(array) Stream<Integer> s = Arrays.stream(arr);

三、Stream 常用 API 方法

所有 Stream 方法可分为两类:

  • 中间操作(非终结方法):返回 Stream 本身,可继续链式调用;

  • 终结操作:执行最终计算,不返回 Stream。

3.1 非终结方法(中间操作)

方法 功能说明 示例
filter(Predicate) 过滤符合条件的元素 list.stream().filter(x -> x > 10)
skip(long n) 跳过前 n 个元素 stream.skip(2)
limit(long n) 取前 n 个元素 stream.limit(5)
map(Function) 元素映射(转换) list.stream().map(String::toUpperCase)
distinct() 去重 stream.distinct()
sorted() 自然排序 stream.sorted()
sorted(Comparator) 自定义排序 stream.sorted((a, b) -> b - a)
concat(a, b) 拼接两个流 Stream.concat(s1, s2)

3.2 终结方法(最终操作)

方法 功能说明 示例
forEach(Consumer) 遍历输出 stream.forEach(System.out::println)
count() 统计数量 long c = stream.count();
collect(Collectors.toList()) 转换为集合 List<String> res = stream.collect(Collectors.toList());
reduce() 归约计算(聚合) Optional<Integer> sum = list.stream().reduce(Integer::sum);
anyMatch() 判断是否有符合条件的元素 stream.anyMatch(x -> x > 0)
allMatch() 判断是否所有元素都满足条件 stream.allMatch(x -> x != null)
noneMatch() 判断是否没有符合条件的元素 stream.noneMatch(x -> x < 0)

四、reduce(约归操作)

reduce() 用于将流中元素反复结合,得到一个值。常用于求和、求最大值、字符串拼接等。

常见写法:

Optional<Integer> sum = list.stream().reduce(Integer::sum);
Optional<Integer> max = list.stream().reduce(Integer::max);
Optional<String> concat = list.stream().reduce(String::concat);

说明:

  • Integer::sum —— 求和

  • Integer::max —— 求最大值

  • String::concat —— 拼接字符串

  • reduce() 返回 Optional<T>,可用 .get().orElse() 获取。

五、Stream 流常用方法速查表

分类 方法 功能简述
获取流 stream()of()Arrays.stream() 从集合或数组创建流
过滤 filter() 筛选满足条件的元素
转换 map()flatMap() 元素类型转换或扁平化
排序 sorted() 对流中元素排序
去重 distinct() 去除重复元素
截取 limit()skip() 获取或跳过部分数据
统计 count()max()min() 统计与聚合操作
聚合 reduce() 自定义归约计算
收集 collect() 转换为集合或字符串
遍历 forEach() 遍历输出
匹配 anyMatch()allMatch()noneMatch() 条件判断

六、Stream 综合实战题:图书馆借阅分析

6.1 场景背景

图书馆系统中记录了多位读者(Reader)及他们的借阅记录(Borrow)。 每位读者有姓名与所在城市,每条借阅记录包括借阅者、借阅年份以及书本价格。

请使用 Stream API 完成以下分析任务。

6.2 代码准备

import java.util.*;
import java.util.stream.*;
​
public class Test {
    public static void main(String[] args) {
        Reader tom = new Reader("Tom", "Beijing");
        Reader lucy = new Reader("Lucy", "Shanghai");
        Reader alan = new Reader("Alan", "Beijing");
        Reader lily = new Reader("Lily", "Shenzhen");
        Reader john = new Reader("John", "Shanghai");
​
        List<Borrow> borrows = Arrays.asList(
            new Borrow(tom, 2021, 60),
            new Borrow(lucy, 2022, 120),
            new Borrow(alan, 2021, 90),
            new Borrow(lily, 2023, 200),
            new Borrow(john, 2021, 150),
            new Borrow(lucy, 2023, 50),
            new Borrow(alan, 2022, 80)
        );
​
        // 请在此完成题目要求👇
    }
}

6.3 类定义

class Reader {
    private String name;
    private String city;
​
    public Reader(String name, String city) {
        this.name = name;
        this.city = city;
    }
​
    public String getName() { return name; }
    public String getCity() { return city; }
​
    @Override
    public String toString() {
        return name + " from " + city;
    }
}
​
class Borrow {
    private Reader reader;
    private int year;
    private int price;
​
    public Borrow(Reader reader, int year, int price) {
        this.reader = reader;
        this.year = year;
        this.price = price;
    }
​
    public Reader getReader() { return reader; }
    public int getYear() { return year; }
    public int getPrice() { return price; }
​
    @Override
    public String toString() {
        return reader.getName() + " borrowed a book in " + year + " costing " + price;
    }
}

6.4 题目要求

1️⃣ 找出 2021 年所有借阅记录,并按书价升序排序。

2️⃣ 查询所有读者所在的不同城市

3️⃣ 查找所有来自 北京(Beijing) 的读者,并按姓名排序。

4️⃣ 返回所有读者的姓名字符串,按字母顺序排序

5️⃣ 是否存在读者在 深圳(Shenzhen) 借阅过图书?

6️⃣ 打印出生活在 上海(Shanghai) 的读者的所有借阅金额。

7️⃣ 所有借阅中,最高的书价是多少?

8️⃣ 找到价格最低的借阅记录

6.5 题解参考

// 1️⃣ 2021年借阅记录(按书价升序)
borrows.stream()
       .filter(b -> b.getYear() == 2021)
       .sorted(Comparator.comparing(Borrow::getPrice))
       .forEach(System.out::println);
​
// 2️⃣ 读者所在城市(去重)
borrows.stream()
       .map(b -> b.getReader().getCity())
       .distinct()
       .forEach(System.out::println);
​
// 3️⃣ 来自北京的读者(按姓名排序)
borrows.stream()
       .map(Borrow::getReader)
       .filter(r -> r.getCity().equals("Beijing"))
       .distinct()
       .sorted(Comparator.comparing(Reader::getName))
       .forEach(System.out::println);
​
// 4️⃣ 所有读者姓名按字母顺序
String names = borrows.stream()
        .map(b -> b.getReader().getName())
        .distinct()
        .sorted()
        .collect(Collectors.joining(", "));
System.out.println(names);
​
// 5️⃣ 是否有深圳的读者借阅
boolean hasShenzhen = borrows.stream()
        .anyMatch(b -> b.getReader().getCity().equals("Shenzhen"));
System.out.println(hasShenzhen);
​
// 6️⃣ 上海读者的借阅金额
borrows.stream()
       .filter(b -> b.getReader().getCity().equals("Shanghai"))
       .map(Borrow::getPrice)
       .forEach(System.out::println);
​
// 7️⃣ 最高书价
int maxPrice = borrows.stream()
        .map(Borrow::getPrice)
        .reduce(Integer::max)
        .orElse(0);
System.out.println("最高书价:" + maxPrice);
​
// 8️⃣ 最低价借阅记录
Borrow minBorrow = borrows.stream()
        .min(Comparator.comparing(Borrow::getPrice))
        .orElse(null);
System.out.println(minBorrow);
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐