Java 8 Stream API 详解(java stream.)
bigegpt 2025-06-30 14:49 5 浏览
Java 8 Stream API 详解
一、概述
在 Java 8 中,Stream API 是一个重要的新特性。它为处理集合(如 List、Set 等)中的元素提供了一种高效且富有表现力的方式。Stream API 允许开发者以声明式的方式处理数据,将数据处理逻辑与数据存储结构分离,使得代码更加简洁、易读和可维护。同时,Stream API 支持并行处理,能够充分利用多核处理器的性能。
二、Stream 的概念
2.1 什么是 Stream
Stream 不是一种数据结构,它是对数据源(如集合、数组等)的元素进行一系列操作的抽象。可以将 Stream 看作是一个高级迭代器,它允许我们以一种更灵活的方式遍历和处理集合中的元素。
2.2 Stream 的特点
- 不存储数据:Stream 只是对数据源中的元素进行操作,不存储元素本身。
- 函数式编程:使用 Lambda 表达式来定义操作,代码简洁且易于理解。
- 延迟执行:Stream 的中间操作不会立即执行,只有在调用终止操作时才会触发执行。
- 可并行操作:Stream 可以并行处理元素,提高处理效率。
三、创建 Stream
3.1 从集合创建 Stream
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamCreationFromCollection {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("apple");
fruits.add("banana");
fruits.add("cherry");
// 创建顺序流
Stream<String> sequentialStream = fruits.stream();
// 创建并行流
Stream<String> parallelStream = fruits.parallelStream();
}
}
3.2 从数组创建 Stream
import java.util.stream.Stream;
public class StreamCreationFromArray {
public static void main(String[] args) {
String[] colors = {"red", "green", "blue"};
Stream<String> colorStream = Stream.of(colors);
}
}
3.3 使用 Stream.generate() 和 Stream.iterate() 创建无限流
import java.util.stream.Stream;
public class InfiniteStreamCreation {
public static void main(String[] args) {
// 使用 generate 创建无限流,生成随机数
Stream<Double> randomStream = Stream.generate(Math::random);
randomStream.limit(5).forEach(System.out::println);
// 使用 iterate 创建无限流,从 0 开始,每次递增 2
Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2);
evenStream.limit(5).forEach(System.out::println);
}
}
四、Stream 的操作
4.1 中间操作
中间操作会返回一个新的 Stream,并且不会立即执行,常见的中间操作有:
4.1.1 过滤(filter)
import java.util.Arrays;
import java.util.List;
public class FilterOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
}
}
4.1.2 映射(map)
import java.util.Arrays;
import java.util.List;
public class MapOperation {
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world");
words.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
}
4.1.3 扁平化映射(flatMap)
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class FlatMapOperation {
public static void main(String[] args) {
List<List<Integer>> nestedList = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
Stream<Integer> flatStream = nestedList.stream()
.flatMap(List::stream);
flatStream.forEach(System.out::println);
}
}
4.1.4 排序(sorted)
import java.util.Arrays;
import java.util.List;
public class SortedOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);
numbers.stream()
.sorted()
.forEach(System.out::println);
// 自定义排序
numbers.stream()
.sorted((a, b) -> b - a)
.forEach(System.out::println);
}
}
4.1.5 去重(distinct)
import java.util.Arrays;
import java.util.List;
public class DistinctOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
numbers.stream()
.distinct()
.forEach(System.out::println);
}
}
4.1.6 截断(limit)和跳过(skip)
import java.util.Arrays;
import java.util.List;
public class LimitAndSkipOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// 取前 3 个元素
numbers.stream()
.limit(3)
.forEach(System.out::println);
// 跳过前 2 个元素
numbers.stream()
.skip(2)
.forEach(System.out::println);
}
}
4.2 终止操作
终止操作会触发中间操作的执行,并产生一个最终结果,常见的终止操作有:
4.2.1 遍历(forEach)
import java.util.Arrays;
import java.util.List;
public class ForEachOperation {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.forEach(System.out::println);
}
}
4.2.2 收集(collect)
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class CollectOperation {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Charlie", 25)
);
// 收集到 List
List<String> names = people.stream()
.map(Person::getName)
.collect(Collectors.toList());
// 按年龄分组
Map<Integer, List<Person>> groupedByAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
// 拼接名字
String namesJoined = people.stream()
.map(Person::getName)
.collect(Collectors.joining(", "));
}
}
4.2.3 统计(count)
import java.util.Arrays;
import java.util.List;
public class CountOperation {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream()
.count();
System.out.println("Number of names: " + count);
}
}
4.2.4 查找(findFirst、findAny)
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class FindOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstEven = numbers.stream()
.filter(n -> n % 2 == 0)
.findFirst();
if (firstEven.isPresent()) {
System.out.println("First even number: " + firstEven.get());
}
Optional<Integer> anyEven = numbers.parallelStream()
.filter(n -> n % 2 == 0)
.findAny();
if (anyEven.isPresent()) {
System.out.println("Any even number: " + anyEven.get());
}
}
}
4.2.5 匹配(allMatch、anyMatch、noneMatch)
import java.util.Arrays;
import java.util.List;
public class MatchOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(2, 4, 6, 8);
boolean allEven = numbers.stream()
.allMatch(n -> n % 2 == 0);
System.out.println("All numbers are even: " + allEven);
boolean anyGreaterThanFive = numbers.stream()
.anyMatch(n -> n > 5);
System.out.println("Any number is greater than 5: " + anyGreaterThanFive);
boolean noneGreaterThanTen = numbers.stream()
.noneMatch(n -> n > 10);
System.out.println("None of the numbers is greater than 10: " + noneGreaterThanTen);
}
}
4.2.6 归约(reduce)
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class ReduceOperation {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 无初始值的归约
Optional<Integer> sumWithoutInitial = numbers.stream()
.reduce((a, b) -> a + b);
if (sumWithoutInitial.isPresent()) {
System.out.println("Sum without initial value: " + sumWithoutInitial.get());
}
// 有初始值的归约
int sumWithInitial = numbers.stream()
.reduce(10, (a, b) -> a + b);
System.out.println("Sum with initial value: " + sumWithInitial);
}
}
五、并行流
并行流可以利用多核处理器并行处理元素,提高处理效率。但并行流并不适用于所有场景,使用时需要注意线程安全和性能开销。
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream()
.map(n -> n * 2)
.forEach(System.out::println);
}
}
六、Stream 的使用场景和注意事项
6.1 使用场景
- 数据过滤和筛选:当需要从大量数据中筛选出符合条件的元素时,Stream 的 filter 操作非常方便。
- 数据转换:使用 map 和 flatMap 操作可以将数据从一种类型转换为另一种类型。
- 数据分组和聚合:collect 操作可以实现数据的分组和聚合,如按条件分组、求和、计数等。
6.2 注意事项
- 流的一次性使用:Stream 只能被使用一次,一旦调用了终止操作,流就会被关闭,再次使用会抛出 IllegalStateException。
- 并行流的使用:并行流虽然可以提高处理效率,但在数据量较小或操作本身线程安全开销较大时,并行流可能会降低性能。在使用并行流前,需要对数据量和操作复杂度进行评估。
七、总结
Java 8 的 Stream API 为集合数据处理提供了一种强大而灵活的方式。通过声明式的编程风格和丰富的操作方法,开发者可以更高效地处理集合元素,编写更加简洁、易读和可维护的代码。同时,并行流的支持使得在多核处理器上可以充分发挥性能优势。但在使用 Stream API 时,需要注意流的一次性使用和并行流的适用场景。
你觉得这篇关于 Java 8 Stream API 的文章如何?如果你对文章还有其他的想法,比如增加某些 API 的详细使用案例、修改内容侧重点等,都可以随时告诉我。
相关推荐
- LangChain4j如何自定义文档转换器实现数据清洗?
-
LangChain4j提供了3种RAG(Retrieval-AugmentedGeneration,检索增强生成)实现,我们通常在原生或高级的RAG实现中,要对数据进行清洗,也就是将外接...
- Java 8 Stream API 详解(java stream.)
-
Java8StreamAPI详解一、概述在Java8中,StreamAPI是一个重要的新特性。它为处理集合(如List、Set等)中的元素提供了一种高效且富有表现力的方式。Str...
- Java修炼终极指南:185 使用 Stream 过滤嵌套集合
-
这是面试中的一个经典问题,通常从一个模型开始,如下所示(我们假设集合是一个List):publicclassAuthor{privatefinalStringname;pri...
- java8的stream使用小示例(java stream())
-
据JetBrains发布的2021年开发者生态系统调查,Java8在java使用的版本中仍然是当前最流行的版本。72%的专业开发人员使用Java8作为其在java开发中主要编程语言版本。现...
- Node.js Stream - 实战篇(node.js in action)
-
本文转自“美团点评技术团队”http://tech.meituan.com/stream-in-action.html背景前面两篇(基础篇和进阶篇)主要介绍流的基本用法和原理,本篇从应用的角度,介...
- Java Stream:集合处理的api(java 集合操作)
-
JavaStream流:高效集合处理的函数式编程利器一、什么是JavaStream?Java8引入的StreamAPI是一套用于处理集合数据的流式编程接口,通过函数式风格(无副作用的...
- 去除 List 中的重复元素,你知道几种实现方法?
-
去除List中重复元素,这在实际编程或面试中经常遇到,每个人都有习惯的写法吧,这里抛砖引玉,汇总了一些实现方案,开拓思路。准备数据假设数组中有10个数据,可能有重复,需要将重复的数据从数组中去掉。pu...
- Java开发者必看!Stream流式编程10个爆款技巧,让你代码优雅飞起
-
为什么你的Java代码总像拧巴的麻绳?掌握这10个Stream实战技巧,代码效率与优雅度将产生质的飞跃。以下案例均来自真实电商系统场景,带你感受流式编程的降维打击!一、过滤与映射组合拳(Filter...
- leetcode每日一题之存在重复元素(存在重复元素 iii)
-
题:给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回true。如果数组中每个元素都不相同,则返回false。比如:输入:[1,2,3,1]输出:true...
- 告别for循环!揭秘Stream API如何让你的代码简洁度提升300%
-
一、当传统循环遇上现代需求真实场景复现:某电商平台需要处理10万条订单数据,要求:筛选出金额>500的订单提取用户ID并去重统计VIP用户数量传统实现方案://常规写法Set<Long...
- Java中List去重的N种方法:从基础到优雅
-
Java中List去重的N种方法:从基础到优雅在日常的Java开发中,我们经常会遇到需要对List集合去重的情况。无论是为了清理重复的数据,还是为了优化算法性能,掌握多种去重方式都是一项非常实用的技能...
- Java Stream流没用过?常用高频方法
-
概念Stream流是Java8添加的以一种链式调用的方法处理数据,主要侧重于计算。具有以下相关特点代码简洁链式调用Stream常用方法1.将数组变为当作List操作String[]strArr=...
- 核医学专业名词索引(M-R)(核医学重点归纳)
-
M吗啡(morphia)埋藏式心律转复除颤器(implantablecardioverterdefibrillator,ICD)麦角骨化醇(VD2,calciferol)脉冲堆积(pulsepi...
- CodeMeter 新版发布(codesigner下载)
-
威步于2022年8月4日发布CodeMeter7.50及CodeMeter软件保护套装11.10,以下为新版内容。CodeMeterRuntime7.50StreamingSIMDExten...
- 世界上最小的五轴铣床Pocket NC(最小的五轴加工中心)
-
PocketNC,由MIT学生研制,还有说法是这款产品的设计者是来自美国蒙大拿州的一对极客夫妻。目前主要有两款产品:PocketNCV2-50,9000美元;PocketNCV2-10,60...
- 一周热门
- 最近发表
-
- LangChain4j如何自定义文档转换器实现数据清洗?
- Java 8 Stream API 详解(java stream.)
- Java修炼终极指南:185 使用 Stream 过滤嵌套集合
- java8的stream使用小示例(java stream())
- Node.js Stream - 实战篇(node.js in action)
- Java Stream:集合处理的api(java 集合操作)
- 去除 List 中的重复元素,你知道几种实现方法?
- Java开发者必看!Stream流式编程10个爆款技巧,让你代码优雅飞起
- leetcode每日一题之存在重复元素(存在重复元素 iii)
- 告别for循环!揭秘Stream API如何让你的代码简洁度提升300%
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)