Java8-Stream流介绍和使用案例
Java 8 引入了 Stream API,它提供了一种高效且声明式的方式来处理集合数据。Stream 的核心思想是将数据的操作分为中间操作(Intermediate Operations)和终端操作(Terminal Operations),并通过流水线(Pipeline)的方式执行。
以下是 Java 8 Stream 的特性及常用案例:
1. Stream 的特性
1.1 声明式编程
Stream 使用声明式的方式处理数据,开发者只需关注“做什么”,而不是“怎么做”。例如:
list.stream().filter(x -> x > 10).forEach(System.out::println);
1.2 惰性求值(Lazy Evaluation)
Stream 的中间操作不会立即执行,只有在终端操作触发时才会执行。例如:
list.stream().filter(x -> x > 10); // 不会立即执行
1.3 不可重复使用
Stream 是一次性的,一旦执行了终端操作,Stream 就会被关闭,不能重复使用。
1.4 并行处理
Stream 可以轻松地并行化处理数据,只需调用 parallel()
方法:
list.parallelStream().filter(x -> x > 10).forEach(System.out::println);
2. Stream 的操作类型
2.1 中间操作(Intermediate Operations)
中间操作返回一个新的 Stream,可以链式调用。常见的中间操作包括:
filter()
:过滤元素。map()
:将元素映射为另一种形式。sorted()
:排序。distinct()
:去重。limit()
:限制元素数量。skip()
:跳过前 N 个元素。
2.2 终端操作(Terminal Operations)
终端操作会触发 Stream 的执行,并返回一个非 Stream 的结果。常见的终端操作包括:
forEach()
:遍历元素。collect()
:将 Stream 转换为集合。reduce()
:将 Stream 中的元素归约为一个值。count()
:统计元素数量。anyMatch()
、allMatch()
、noneMatch()
:匹配元素。findFirst()
、findAny()
:查找元素。
3. 常用案例
3.1 过滤数据
使用 filter()
过滤集合中满足条件的元素:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(x -> x % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // 输出: [2, 4, 6]
3.2 映射数据
使用 map()
将集合中的元素映射为另一种形式:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(nameLengths); // 输出: [5, 3, 7]
3.3 排序
使用 sorted()
对集合中的元素进行排序:
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNames); // 输出: [Alice, Bob, Charlie]
3.4 去重
使用 distinct()
去除集合中的重复元素:
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> uniqueNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueNumbers); // 输出: [1, 2, 3, 4, 5]
3.5 统计
使用 count()
统计元素数量:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream().count();
System.out.println(count); // 输出: 3
3.6 归约
使用 reduce()
将集合中的元素归约为一个值:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum); // 输出: 15
3.7 分组
使用 Collectors.groupingBy()
对集合中的元素进行分组:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna");
Map<Character, List<String>> groupedNames = names.stream()
.collect(Collectors.groupingBy(name -> name.charAt(0)));
System.out.println(groupedNames); // 输出: {A=[Alice, Anna], B=[Bob], C=[Charlie]}
3.8 并行处理
使用 parallelStream()
并行处理数据:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = numbers.parallelStream()
.filter(x -> x % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // 输出: [2, 4, 6, 8, 10]
3.9 匹配
使用 anyMatch()
、allMatch()
、noneMatch()
进行匹配:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream().anyMatch(x -> x % 2 == 0);
boolean allEven = numbers.stream().allMatch(x -> x % 2 == 0);
boolean noneNegative = numbers.stream().noneMatch(x -> x < 0);
System.out.println(hasEven); // 输出: true
System.out.println(allEven); // 输出: false
System.out.println(noneNegative); // 输出: true
3.10 查找
使用 findFirst()
和 findAny()
查找元素:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> first = names.stream().findFirst();
Optional<String> any = names.stream().findAny();
System.out.println(first.get()); // 输出: Alice
System.out.println(any.get()); // 输出: Alice 或 Bob 或 Charlie
4. 总结
Java 8 的 Stream API 提供了一种高效、简洁的方式来处理集合数据。它的主要特点包括:
- 声明式编程:代码更简洁易读。
- 惰性求值:提高性能。
- 并行处理:轻松实现并行化。
常用操作包括:
- 过滤(
filter
)、映射(map
)、排序(sorted
)、去重(distinct
)。 - 统计(
count
)、归约(reduce
)、分组(groupingBy
)。 - 匹配(
anyMatch
、allMatch
、noneMatch
)、查找(findFirst
、findAny
)。
通过 Stream API,可以大大简化集合操作的代码,并提高开发效率。