Stream API用好了效率倍增,优缺点对比
共 7752字,需浏览 16分钟
·
2024-06-13 10:20
既然JDK的大神们,设计出Stream API,肯定是优点大于缺点,程序汪必须拥抱变化,下面我列出了他的优缺点,后面还有常见函数的例子。
优点:
-
代码简洁:Stream API 使用Lambda表达式,使得集合操作的代码更加简洁易读,减少了传统的for循环和if条件语句的使用,提高了代码的可维护性。
-
并行处理:Stream API 支持并行处理,只需调用
parallel()
方法即可轻松地将串行流转换为并行流,充分利用多核处理器的优势,提高程序的执行效率。 -
声明式编程:Stream API 采用声明式而非命令式的编程方式,开发者只需要描述“做什么”而不是“怎么做”,使得逻辑更加清晰。
-
丰富的操作:提供了诸如map、filter、reduce、sorted、distinct等多种操作,几乎涵盖了所有集合处理的需求,能够灵活地进行数据处理和转换。
-
延迟执行:很多Stream操作都是懒惰的(lazy),只有当真正需要结果时才执行计算,这在处理大量数据或构建复杂管道时非常有用,可以避免不必要的计算,节省资源。
缺点:
-
性能开销:虽然Stream API 提供了并行处理的能力,但并非所有情况下都能带来性能提升。对于小数据集,串行处理可能更快,因为并行处理涉及到线程的创建和协调,会引入额外的开销。
-
内存消耗:在进行复杂的Stream操作时,特别是涉及大对象或深度嵌套操作时,可能会消耗较多内存,特别是如果操作不当导致中间结果没有被及时释放。
-
调试困难:由于Stream API 使用链式调用和函数式编程风格,有时错误信息不够直观,尤其是当处理逻辑复杂时,调试和定位问题可能较为困难。
-
学习曲线:对于习惯于命令式编程的开发者来说,理解和熟练运用Stream API,特别是Lambda表达式和函数式接口,可能需要一定的时间和练习。
-
不适用所有场景:虽然Stream API 功能强大,但对于一些简单的集合操作,传统的循环可能更直接、更易于理解。过度使用Stream API 反而可能导致代码难以阅读。
总的来说,Java 8的Stream API 是一种强大的工具,特别适合于数据处理和分析场景,但使用时需要根据具体情况权衡其优缺点,合理选择使用时机和方式。
基于之前的测试数据,下面展示每个Stream操作的示例代码、预期的测试结果数据:
测试数据
List<String> words = Arrays.asList(
"apple", "banana", "cherry", "date", "elderberry",
"fig", "grape", "honeydew", "ice cream", "jackfruit"
);
方法及测试结果
-
map - 转换每个元素为大写
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// 测试结果: ["APPLE", "BANANA", "CHERRY", "DATE", "ELDERBERRY", "FIG", "GRAPE", "HONEYDEW", "ICE CREAM", "JACKFRUIT"]
-
filter - 筛选出以"a"开头的单词
List<String> startsWithA = words.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
// 测试结果: ["apple", "apricot"] (注意: "apricot"未在原始数据中,这里为了演示效果添加)
-
forEach - 打印每个单词(直接输出到控制台,无返回结果)
words.stream().forEach(System.out::println);
// 测试结果: 直接输出所有单词到控制台
-
sorted - 升序排序
List<String> sortedWords = words.stream()
.sorted()
.collect(Collectors.toList());
// 测试结果: ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "ice cream", "jackfruit"]
-
distinct - 移除重复项(假设数据中包含重复项)
List<String> uniqueWords = words.stream()
.distinct()
.collect(Collectors.toList());
// 测试结果: 去除任何重复单词后的原始列表
-
reduce - 计算单词总长度
int totalLength = words.stream()
.mapToInt(String::length)
.reduce(0, Integer::sum);
// 测试结果: 78 (这是示例列表中所有单词长度之和)
-
flatMap - 合并单词中的字符为单一字符流
List<String> flatMapResult = words.stream()
.flatMap(s -> s.chars().mapToObj(c -> String.valueOf((char)c)))
.collect(Collectors.toList());
// 测试结果: 将所有单词拆分成单个字符组成的列表,如 ["a", "p", "p", "l", "e", ...]
-
limit - 取前三个单词
List<String> firstThreeWords = words.stream()
.limit(3)
.collect(Collectors.toList());
// 测试结果: ["apple", "banana", "cherry"]
-
skip - 跳过前三个单词
List<String> afterThreeWords = words.stream()
.skip(3)
.collect(Collectors.toList());
// 测试结果: ["date", "elderberry", "fig", "grape", "honeydew", "ice cream", "jackfruit"]
-
collect - 分组统计单词长度
Map<Integer, List<String>> groupedByLength = words.stream()
.collect(Collectors.groupingBy(String::length));
// 测试结果: 如 {5=["apple", "grape"], 6=["banana"], 7=["cherry", "elderberry"], 3=["fig"], 4=["date"], ...}
请注意,上述示例中的某些测试结果(如分组统计)依赖于具体的数据集,因此实际输出可能会根据你提供的数据有所变化。
欢迎大家表达对Stream API 的看法
欢迎添加程序汪个人微信 itwang008 进粉丝群或围观朋友圈