写点什么

Java Streams 的潜力

作者:FunTester
  • 2024-09-06
    河北
  • 本文字数:2374 字

    阅读完需:约 8 分钟

Java Streams 是 Java 8 引入后,彻底改变了开发者处理集合的方式。Java Streams 已经成为处理集合的必备工具。它们不仅让数据处理变得更加简洁、易读,还显著提升了代码的可维护性和开发者的生产力。尽管 filtermap 是基本操作,但 Java Streams API 中还有很多值得探索的高级用法。


在这篇文章中,我将介绍 5 个实用技巧,帮助你更好地运用 Java Streams。这些方法不仅能简化复杂的数据转换,还能让你的代码更加清晰和高效。

精准过滤

入门

想象一下,你有一个产品列表,想要筛选出有趣的灵魂测试工程师。filter 操作是实现这一目标的利器。来看个例子:


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        List<FunTester> funTesters = testers.stream()              .filter(tester -> tester.getSoul().contains("Fun"))              .collect(Collectors.toList());  }
复制代码


这段代码从 testers 列表中创建了一个流,并通过 filter 筛选出有趣的灵魂(Teseter),最后将结果收集到一个新的 funTesters 列表中。

进阶

filter 的强大之处在于你可以轻松地组合多个条件。例如,如果你还想筛选出特定类别(比如成年的),可以再加一个 filter


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        List<FunTester> funTesters = testers.stream()              .filter(tester -> tester.getSoul().contains("Fun"))              .filter(tester -> tester.getAge() > 18)              .collect(Collectors.toList());  }
复制代码


通过组合多个条件,你可以更加精准地获取需要的结果。

map 转换

入门

map 操作可以对流中的每个元素进行转换。它接收一个函数(通常是 Lambda 表达式),将其应用于每个元素,生成一个包含转换结果的新流。


来看个简单的例子:


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        List<String> souls = testers.stream()              .map(FunTester::getSoul)              .collect(Collectors.toList());  }
复制代码


在这个例子中,我们使用 map 提取每个 Testersoul,生成一个 String 的列表。

进阶

我们可以在 map 之前或之后添加 filter 操作,来筛选和转换数据。例如,只处理非空的 soul 属性:


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        List<String> souls = testers.stream()              .map(FunTester::getSoul)              .filter(Objects::nonNull) // 过滤掉空值              .map(String::trim) // 去除首尾空格              .collect(Collectors.toList());  }
复制代码


map 的用途非常广泛,不仅限于简单的数据提取,还能用于更复杂的转换。

汇总

入门

reduce 操作可以将流中的元素累积成一个单一结果,非常适合进行统计或数据汇总。比如,计算所有 Tester 的 BUG 总数:


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        int bugs = testers.stream()              .mapToInt(FunTester::getBugs)// 获取所有测试工程师的 bug 数量              .reduce(0, Integer::sum);// 计算总 bug 数量  }
复制代码


这段代码演示了如何使用 Java Streams API 高效地计算 List 中所有 FunTester 对象的 BUG 总数。使用 mapToInt 提取 int 值并通过 reduce 计算总和是处理这类问题的常见模式。这种方法简洁而强大,适用于各种类似的数据处理场景。

进阶

reduce 还能用于其他类型的汇总操作。比如,找出最便宜的商品:


FunTester funTester = testers.stream()          .reduce((t1, t2) -> t1.getBugs() > t2.getBugs() ? t1 : t2)          .get();  System.out.println("BUG 最多的灵魂测试工程师是:" + funTester.getName());
复制代码


在这个例子中,reduce 用于比较每个 Tester 的 BUG 数量,找出 BUG 最多的那个,把他揪出来。

分组

基础

groupBy 是 Java Streams API 中的一个强大功能,它允许你根据某个特性将流中的元素分组。通过 groupBy,你可以将具有相似属性的元素归类到同一个集合中,从而方便地进行进一步的分析和处理。


比如将 Tester 根据司龄进行分组:


Map<Integer, List<FunTester>> collect = testers.stream().collect(Collectors.groupingBy(FunTester::getCompanyYears));
复制代码


代码演示了如何使用 Java Streams API 将 FunTester 对象按司龄(getCompanyYears)进行分组。以下是完整示例,展示了如何按工作年限对 FunTester 对象进行分组,并输出分组结果。

进阶

Java Streams 甚至支持嵌套分组。例如可以先根据司龄进行分组,然后再根据实际年龄分组。


public static void main(String[] args) {      List<FunTester> testers = new ArrayList<>();        Map<Integer, Map<String, List<FunTester>>> collect = testers.stream()              .collect(Collectors.groupingBy(FunTester::getCompanyYears, Collectors.groupingBy(t -> {          if (t.getAge() > 35) {// 年龄大于35岁,则分组              return "年龄大";          } else {              return "年龄小";          }      })));  }
复制代码


通过嵌套的 groupingBy,你可以将数据进行多层次的分组,使得组织数据更为灵活。

Java Streams 的潜力

Java Streams 的强大功能远不止于此。随着你深入探索这个 API 的更多特性,你会发现它不仅能帮助你处理集合数据,还能极大地提升代码的可读性和维护性。通过不断实践和应用,你将逐渐掌握这些工具的精髓,使得代码变得更加高效、简洁、优雅。不论是处理复杂的数据转换,还是实现更灵活的操作,Java Streams 都能为你提供无穷的可能性,让你的编程技巧更上一层楼。

发布于: 刚刚阅读数: 2
用户头像

FunTester

关注

公众号:FunTester,800篇原创,欢迎关注 2020-10-20 加入

Fun·BUG挖掘机·性能征服者·头顶锅盖·Tester

评论

发布
暂无评论
Java Streams 的潜力_FunTester_InfoQ写作社区