Java 8 引入了 Stream API,它提供了一种新的抽象,使得在集合数据上进行函数式编程变得更加简单、高效和可维护。下面我们将探讨 Stream API 的几个常用方法和功能:
创建流
创建流操作
● 从集合创建:
使用 stream() 方法从集合(如 List、Set、Map)创建 Stream。
java
List<String> myList = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = myList.stream();
● 从数组创建:
使用 Arrays.stream() 方法从数组创建 Stream。
java
int[] numbers = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(numbers);
中间操作
filter()
● 注意事项:
○ 用于筛选流中的元素,需提供一个 Predicate。
○ 操作结果是一个新的 Stream,其中只包含符合条件的元素。
○ 注意 Predicate 条件的复杂性和可读性。
java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 输出筛选后的偶数列表 [2, 4]
System.out.println(evenNumbers);
map()
● 注意事项:
○ 用于将流中的每个元素映射成另一个元素。
○ 映射函数应保持无状态,不修改外部变量。
java
javaCopy code
List<String> words = Arrays.asList("apple", "banana", "orange");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// 输出单词长度列表 [5, 6, 6]
System.out.println(wordLengths);
当使用 Java Stream API 时,每个方法都有一些注意事项需要考虑。以下是常用 Stream API 方法、相关的注意事项和例子的整合:
filter()
● 注意事项:
○ 用于筛选流中的元素,需提供一个 Predicate。
○ 操作结果是一个新的 Stream,其中只包含符合条件的元素。
○ 注意 Predicate 条件的复杂性和可读性。
java
javaCopy code
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 输出筛选后的偶数列表 [2, 4]
System.out.println(evenNumbers);
map()
● 注意事项:
○ 用于将流中的每个元素映射成另一个元素。
○ 映射函数应保持无状态,不修改外部变量。
java
javaCopy code
List<String> words = Arrays.asList("apple", "banana", "orange");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// 输出单词长度列表 [5, 6, 6]
System.out.println(wordLengths);
distinct()
● 注意事项:
○ 用于去除流中的重复元素,基于 equals() 方法进行判断。
○ 要确保正确实现了对象的 equals() 方法。
java
javaCopy code
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> uniqueNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
// 输出去重后的数字列表 [1, 2, 3, 4, 5]
System.out.println(uniqueNumbers);
sorted()
● 注意事项:
○ 用于对流中的元素进行排序,可自然排序或自定义排序。
○ 自定义排序需保证正确性和稳定性。
java
javaCopy code
List<String> words = Arrays.asList("apple", "banana", "orange");
List<String> sortedWords = words.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
// 输出倒序排序后的单词列表 [orange, banana, apple]
System.out.println(sortedWords);
终端操作:
forEach()
● 注意事项:
○ 对流中的每个元素执行指定操作,适合简单的遍历操作。
○ 不保证元素的处理顺序。
java
List<String> fruits = Arrays.asList("apple", "banana", "orange");
fruits.stream()
.forEach(System.out::println);
// 输出所有水果名称(无序输出)
// apple
// banana
// orange
collect()
注意事项:
● 用于将流中的元素收集到集合或其他数据结构中。
Collectors.toList()
● 用途:
○ toList() 方法将流中的元素收集到一个 List 中。
java
List<String> words = Arrays.asList("Java", "Stream", "API");
List<String> collectedList = words.stream()
.collect(Collectors.toList());
// 将流中的元素收集到 List 中
System.out.println(collectedList); // 输出:[Java, Stream, API]
Collectors.toSet()
● 用途:
○ toSet() 方法将流中的元素收集到一个 Set 中。
java
javaCopy code
List<String> words = Arrays.asList("Java", "Stream", "API");
Set<String> collectedSet = words.stream()
.collect(Collectors.toSet());
// 将流中的元素收集到 Set 中
System.out.println(collectedSet); // 输出:[Java, Stream, API](无序)
Collectors.toMap()
● 用途:
○ toMap() 方法将流中的元素按照键值对的方式收集到一个 Map 中。
java
javaCopy code
List<String> words = Arrays.asList("Java", "Stream", "API");
Map<Integer, String> collectedMap = words.stream()
.collect(Collectors.toMap(String::length, s -> s));
// 将流中的元素按照长度作为键收集到 Map 中
System.out.println(collectedMap); // 输出:{4=Java, 6=Stream, 3=API}
注意: 这种时候一定要进行去重操作,不然会报错,这里如果出现了重复就保留之前的
allUserList.stream()
.collect(Collectors.toMap( CompanyUserListDO::getName,
CompanyUserListDO::getCloudUserId,
(existing, replacement) -> existing))
Collectors.joining()
● 用途:
○ joining() 方法将流中的元素连接成一个字符串。
java
javaCopy code
List<String> words = Arrays.asList("Java", "Stream", "API");
String concatenated = words.stream()
.collect(Collectors.joining(", "));
// 将流中的元素用逗号连接成字符串
System.out.println(concatenated); // 输出:Java, Stream, API
Collectors.groupingBy()
● 用途:
○ groupingBy() 方法按照某个分类器对流中的元素进行分组,生成一个 Map。
java
javaCopy code
List<String> words = Arrays.asList("Java", "Stream", "API");
Map<Integer, List<String>> groupedByLength = words.stream()
.collect(Collectors.groupingBy(String::length));
// 按照字符串长度对流中的元素进行分组
System.out.println(groupedByLength); // 输出:{3=[Java], 5=[Stream], 3=[API]}
Collectors.partitioningBy()
● 用途:
○ partitioningBy() 方法根据某个条件对流中的元素进行分区,生成一个 Map。
java
javaCopy code
List<String> words = Arrays.asList("Java", "Stream", "API");
Map<Boolean, List<String>> partitionedByLength = words.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 4));
// 根据字符串长度是否大于4对流中的元素进行分区
System.out.println(partitionedByLength); // 输出:{false=[Java, API], true=[S
● 需要考虑线程安全性和并发性。
count()
注意事项:
● 用于获取流中元素的数量,返回值为 long 类型。
● 终端操作前不会开始计算。
java
javaCopy code
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
.filter(n -> n > 2)
.count();
// 输出大于2的数字个数
System.out.println(count); // 输出:3
并行流
● 使用 parallelStream():将 Stream 转换为并行流,实现并行处理,提高处理速度。
java
javaCopy code
List<String> words = Arrays.asList("apple", "banana", "orange");
long count = words.parallelStream()
.filter(w -> w.length() > 5)
.count();
System.out.println(count); // 输出符合条件的元素个数
Stream 的优势
● 简化代码:Stream API 提供了一种更简洁的方式来处理集合数据,减少了冗长的迭代和操作代码。
● 更高的性能:利用并行流进行并行处理,可以充分利用多核处理器,提高程序性能。
结语
Java Stream API 提供了丰富的功能和便利的方法,用于处理集合数据,让数据操作更加灵活高效。通过使用 Stream API,可以以更简洁和直观的方式处理集合数据,从而提高编程效率和代码质量。