Java8 Stream 流式编程

本文深入解析 Java 8 引入的 Stream API,涵盖如何从 Collection 创建流,使用 filter、map、flatMap 等方法进行数据处理,以及如何实现排序、去重、聚合等高级操作。

简介

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

1.Collection创建流
stream() : 为集合创建串行流
parallelStream() : 为集合创建并行流

List<String> list = Arrays.asList("A", "B", "C", "D");
// 创建串行流对象
Stream stream = list.stream();
// 创建并行流对象
Stream parallelStream = list.parallelStream();

2.Stream常用方法
filter
过滤元素,通过设置条件过滤元素

List<String> list = Arrays.asList("A", "", "B", "", "C", "D");
// 过滤掉空元素
List<String> filtered = list.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
filtered.forEach(n -> System.out.println(n));

map
元素一对一转换

List<String> list = Arrays.asList("1", "2", "3", "4");
// mapToInt 字符串转int
list.stream().mapToInt(v -> Integer.valueOf(v)).forEach(System.out::println); // 1 2 3 4
// mapToLong 字符串转long
list.stream().mapToLong(v -> Long.valueOf(v)).forEach(System.out::println); // 1 2 3 4
// mapToDouble 字符串转double
list.stream().mapToDouble(v -> Double.valueOf(v)).forEach(System.out::println); // 1.0 2.0 3.0 4.0

peek

List<String> list = Arrays.asList("1", "2", "3", "4");
// peek对Stream中的元素进行操作后,并不会把操作后的数据返回到Stream,所以其中的元素不变。
list.stream().peek(v -> Double.valueOf(v)).forEach(System.out::println); // 1 2 3 4

flatMap
元素一对多转换

List<String> list = Arrays.asList("1,2", "3", "4", "5");
// 元素一对多转换 
List<String> resList = list.stream().flatMap(v -> Stream.of(v.split(","))).collect(Collectors.toList());
resList.forEach(System.out::println); // 1 2 3 4 5

distinct
去掉重复元素

List<String> list = Arrays.asList("1", "1", "2", "3");
// 去重
List<String> resList = list.stream().distinct().collect(Collectors.toList());
resList.forEach(System.out::println);// 1 2 3

sorted
排序

List<Integer> list = Arrays.asList(3, 2, 1, 4);
// 排序
List<Integer> resList = list.stream().sorted().collect(Collectors.toList());
resList.forEach(System.out::println); // 1 2 3 4

limit
返回前n个元素

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 返回前2个元素
List<Integer> resList = list.stream().limit(2).collect(Collectors.toList());
resList.forEach(System.out::println); // 1 2

skip
跳过前n个元素

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 跳过前一个元素
List<Integer> resList = list.stream().skip(1).collect(Collectors.toList());
resList.forEach(System.out::println); // 2 3 4

forEach
遍历

List<Integer> list = Arrays.asList(1, 2, 3, 4);
list.stream().forEach(System.out::println); // 1 2 3 4
// 并行 输出顺序不确定
list.parallelStream().forEach(System.out::println);

forEachOrdered
遍历

List<Integer> list = Arrays.asList(1, 2, 3, 4);
list.stream().forEachOrdered(System.out::println); // 1 2 3 4
// 并行 输出顺序确定
list.parallelStream().forEachOrdered(System.out::println);

reduce
进行聚合求值

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 累计
Optional<Integer> sum = list.stream().reduce((a, b) -> {
    return a + b;
});
 System.out.println(sum.get());  //   10

collect
收集元素

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 合并成list
List<Integer> a1 = list.stream().collect(Collectors.toList());

count
返回元素个数

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 返回个数
long count = list.stream().count();

match
判断是否有元素符合条件

List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 判断元素中是否有等于1的 anyMatch 只要有一个元素符合条件时就返回true
boolean anyMatch = list.stream().anyMatch(e -> e == 1);
System.out.println(anyMatch); // true
// 判断元素是否小于5  allMatch 所有元素符合条件才返回true
boolean allMatch = list.stream().allMatch(e -> e < 5);
System.out.println(allMatch);
// 判断元素是否小于5 noneMatch 所有元素都不符合条件时返回true
boolean noneMatch = list.stream().noneMatch(e -> e < 5);
System.out.println(noneMatch);
<think> 首先,用户的问题是:“我想了解Java Stream流式编程相关内容 请问Java Stream流式编程介绍、使用方法和示例”。这基于系统指令,我需要使用中文回答,并遵循所有格式规则。 关键点: - 所有行内数学表达式必须用 $...$,但这里没有数学内容,所以可能不需要。 - 独立公式必须用 $$...$$ 并单独成段,同样,可能不适用。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在引用段落末尾添加引用标识,例如[^1]。 用户提供了三个引用: - 引用[1]:介绍Stream基本概念、特点。 - 引用[2]:展示Stream的链式操作示例。 - 引用[3]:给出skip()方法的例子。 这些引用在回答中需要被引用,末尾自然地添加引用标识。 系统指令说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 用户上一次的问题就是这个,我需要关注用户的需求:介绍、使用方法和示例。 我的回答结构应该清晰,帮助用户逐步解决问题: - 介绍:什么是Java Stream流式编程。 - 使用方法:如何创建和使用Stream。 - 示例:给出代码示例。 - 基于引用,我需要整合它们。 最后,生成相关问题。 大纲: 1. **介绍**:基于引用[1],简述Stream的定义、特点和优势。添加引用标识。 2. **使用方法**:解释如何创建Stream,常见操作方法(如filter, map, sorted, collect),惰性求值等。参考引用[2]的链式操作。 3. **示例**:提供代码示例,参考引用[3]的skip()方法,并扩展更多示例。 4. **结论**:简要总结。 5. **相关问题**:生成相关问题。 确保回答真实可靠,基于Java知识。 代码示例需要用代码块格式: - 在Markdown中,使用```python或```java等。 系统示例中是python,但这里是Java,所以用```java。 回答结构: - 分段清晰。 - 末尾添加引用。 - 最后添加相关问题。 生成相关问题: - 类似示例中的问题,如: - Java Stream的常见操作方法有哪些? - 如何优化Stream性能? - Stream在并行处理中的应用? - 等等。 现在,构建回答内容。 **介绍部分**: - 定义Stream:基于引用[1],StreamJava 8引入的抽象概念,代表处理数据的序列。 - 特点:数据源、数据处理、惰性求值、不可变性、并行处理[^1]。 - 简要说明优势:高效、可扩展、易于使用。 **使用方法**: - 创建Stream:使用集合或数组的stream()方法。 - 操作方法:filter, map, sorted, reduce, collect等。链式操作:保持可读性[^2]。 - 终止操作:如collect(),触发计算。 - 并行处理:parallel()方法。 **示例**: - 基于引用[3],给出skip()和limit()的示例。 - 添加更多例子: - 过滤和映射。 - 排序和收集。 - 代码块:用```java。 **相关问题**: - 列出3-5个相关问题。 引用标识: - 在引用内容的末尾添加[^1], [^2], [^3]。 最终回答: </think> ### Java Stream流式编程介绍、使用方法和示例 Stream流式编程Java 8引入的核心特性,它提供了一种声明式、函数式的数据处理方式,能够高效地操作数据序列(如集合、数组或I/O资源)。Stream API的设计目标是简化复杂的数据处理任务,提升代码的可读性和性能。下面我将从介绍、使用方法和示例三个方面逐步解释。 #### 1. Stream流式编程介绍 Stream(流)代表着一种元素序列的抽象,这些元素可以来自集合、数组或其他数据源。Stream的核心优势在于其惰性求值机制和链式操作结构,能够轻松实现过滤、映射、聚合等操作,而无需修改原始数据源。Stream具有以下关键特点: - **数据源独立性**:Stream可以从多种来源创建,如调用集合的`stream()`方法或数组的`Arrays.stream()`方法[^1]。 - **数据处理链**:提供丰富的中间操作(如filter、map、sorted)和终止操作(如collect、reduce),操作可以组合成流水线式流程[^2]。 - **惰性求值**:操作只在终止操作触发时执行计算,节省资源并优化性能[^1]。 - **不可变性**:Stream操作不修改原始数据,每次操作返回一个新流,确保数据安全[^1]。 - **并行处理**:通过`parallel()`方法转化为并行流,利用多核处理器提升处理速度[^1]。 Stream特别适合处理大数据集或复杂转换逻辑,能显著减少代码量并提高可维护性。 #### 2. 使用方法 Stream的使用分为三个步骤:创建流、应用中间操作、执行终止操作。基本流程如下: - **创建流**:从数据源(如集合或数组)创建Stream对象。 - **中间操作**:定义数据处理逻辑(如过滤、映射、排序),这些操作是惰性的,不会立即执行。 - **终止操作**:触发实际计算并生成结果(如收集到集合或聚合值)。 常用操作方法包括: - **中间操作**: - `filter(Predicate<T>)`:过滤元素,保留满足条件的元素。 - `map(Function<T,R>)`:转换元素,生成新值。 - `sorted()`:排序元素。 - `skip(long n)`:跳过前n个元素。 - `limit(long n)`:限制元素总数。 - **终止操作**: - `collect(Collector)`:将元素收集到集合或其他数据结构。 - `reduce(BinaryOperator<T>)`:聚合元素(如求和)。 - `forEach(Consumer<T>)`:遍历元素。 链式操作是Stream的核心用法,允许将多个操作组合成一个流水线,保持代码简洁: ```java // 示例链式操作结构 List<T> result = source.stream() .filter(...) // 步骤1:过滤 .map(...) // 步骤2:转换 .sorted(...) // 步骤3:排序 .collect(Collectors.toList()); // 终止操作:收集结果 ``` 并行处理可通过`.parallel()`启用,但需注意线程安全问题[^1]。 #### 3. 示例 以下示例展示了Stream的实际应用,基于Java代码。假设有一个`User`类(包含`id`和`name`属性),以及一个用户列表: ```java import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class StreamExample { public static void main(String[] args) { // 创建用户列表 List<User> users = Arrays.asList( new User(1, "Alice"), new User(2, "Bob"), new User(3, "Charlie"), new User(4, "David") ); // 示例1:过滤和映射 - 获取名字长度大于3的用户名列表 List<String> longNames = users.stream() .filter(u -> u.getName().length() > 3) // 过滤名字长度>3的用户 .map(User::getName) // 映射到用户名 .collect(Collectors.toList()); // 收集为List System.out.println("Long names: " + longNames); // 输出: [Alice, Charlie, David] // 示例2:跳过和限制 - 分页查询,跳过前1条,取2条记录 List<User> pagedUsers = users.stream() .skip(1) // 跳过第一个元素 .limit(2) // 限制取2条 .collect(Collectors.toList()); System.out.println("Paged users: " + pagedUsers); // 输出: [User[id=2,name=Bob], User[id=3,name=Charlie]] // 示例3:排序和聚合 - 按ID降序排序,并计算ID总和 int sumId = users.stream() .sorted((u1, u2) -> u2.getId() - u1.getId()) // 降序排序 .mapToInt(User::getId) // 映射到ID值 .reduce(0, Integer::sum); // 求和聚合 System.out.println("Sum of IDs: " + sumId); // 输出: 10 (1+2+3+4=10) } } class User { private int id; private String name; public User(int id, String name) { this.id = id; this.name = name; } // Getter方法省略... @Override public String toString() { return "User[id=" + id + ",name=" + name + "]"; } } ``` 在这些示例中: - 示例1展示了过滤和映射的组合,用于数据清洗和转换。 - 示例2使用了`skip()`和`limit()`,常用于分页逻辑[^3]。 - 示例3结合排序和聚合,演示了复杂数据处理。 Stream流式编程能显著提升代码效率,特别适用于集合操作、数据分析和并行任务。实践中,建议优先使用Stream代替传统循环,以提升代码简洁性和可维护性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值