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,可以大大简化集合操作的代码,并提高开发效率。
