Java Stream 流
·
一、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);更多推荐

所有评论(0)