当前位置: 首页 > article >正文

深入理解Java 8中的Stream API及其应用

深入理解Java 8中的Stream API及其应用

随着Java 8的推出,Java语言引入了许多令人兴奋的新特性,其中最为引人注目的便是Stream API。Stream API 为我们提供了一种全新的集合操作方式,使得数据处理、转换和过滤变得更加简洁、高效。在本文中,我们将深入探讨Java 8中的Stream API,特别是filtermap等常用操作,并通过实际案例展示其强大的应用。

什么是Stream?

Stream 是一个元素序列,支持多种不同类型的操作来处理这些元素。与集合不同,Stream 并不存储数据,而是按需生成数据。它的操作可以分为两类:中间操作终端操作

  • 中间操作(Intermediate Operation):这些操作会返回一个新的Stream,例如filtermapsorted等。中间操作是惰性的,即它们不会立即执行,直到一个终端操作触发它们的执行。
  • 终端操作(Terminal Operation):这些操作会产生一个结果或者副作用,例如forEachcollectreduce等。终端操作执行后,Stream将不再可用。
如何创建Stream?

创建Stream的方式有多种,例如可以从集合、数组、值、文件等创建。

List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

// 从集合创建 Stream
Stream<String> stream = myList.stream();

// 从数组创建 Stream
Stream<String> streamFromArray = Stream.of("a1", "a2", "b1");

// 从数值范围创建 Stream
IntStream intStream = IntStream.range(1, 5);

// 从文件创建 Stream
Stream<String> lines = Files.lines(Paths.get("file.txt"));

这些创建方法非常灵活,使得我们可以根据不同的需求轻松地获得Stream

Stream 中的常用操作
1. filter

filter 操作用于过滤掉不符合条件的元素,只保留满足条件的元素。它接受一个Predicate接口的实现,作为过滤条件。

List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList.stream()
      .filter(s -> s.startsWith("c"))
      .forEach(System.out::println);  // 输出: c2, c1

在这个例子中,filter 操作筛选出了以"c"开头的字符串。

2. map

map 操作用于将流中的每个元素映射成另一个元素。它接收一个Function接口的实现,用于定义映射规则。

List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList.stream()
      .map(String::toUpperCase)
      .forEach(System.out::println);  // 输出: A1, A2, B1, C2, C1

在这个例子中,map 操作将所有字符串转换为大写形式。

3. sorted

sorted 操作用于对流中的元素进行排序。它可以使用自然排序,也可以接受一个自定义的比较器。

List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList.stream()
      .sorted()
      .forEach(System.out::println);  // 输出: a1, a2, b1, c1, c2

以上代码将字符串按照自然顺序排序。

4. collect

collect 是一个终端操作,用于将流中的元素收集到集合、数组或其他结果容器中。它通常结合Collectors类使用。

List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

List<String> filteredList = myList.stream()
      .filter(s -> s.startsWith("c"))
      .collect(Collectors.toList());

System.out.println(filteredList);  // 输出: [c2, c1]

在这个例子中,collect 操作将筛选后的结果收集到一个新的列表中。

5. forEach

forEach 是一个终端操作,用于对流中的每个元素执行给定的操作。它常用于打印或处理元素。

myList.stream()
      .map(String::toUpperCase)
      .forEach(System.out::println);  // 输出: A1, A2, B1, C2, C1
6. reduce

reduce 操作用于将流中的元素组合成一个值。它适用于求和、求积或字符串连接等操作。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.stream()
      .reduce(0, Integer::sum);

System.out.println(sum);  // 输出: 15

在这个例子中,reduce 操作用于对列表中的整数求和。

实际应用案例
案例1:处理用户数据

假设我们有一个用户对象的列表,我们需要找到所有年龄大于18岁且名字以"A"开头的用户,并按名字排序。

class User {
    String name;
    int age;

    User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

List<User> users = Arrays.asList(
    new User("Alice", 23),
    new User("Bob", 20),
    new User("Charlie", 17),
    new User("Anna", 21)
);

List<User> result = users.stream()
    .filter(user -> user.age > 18)
    .filter(user -> user.name.startsWith("A"))
    .sorted(Comparator.comparing(user -> user.name))
    .collect(Collectors.toList());

result.forEach(System.out::println);  // 输出: Alice (23), Anna (21)

在这个示例中,我们结合使用了filtersortedcollect操作,轻松实现了复杂的数据筛选和排序功能。

案例2:统计字符长度

如果我们有一组字符串,需要计算所有字符串的总长度,可以使用以下代码:

List<String> words = Arrays.asList("Java", "Stream", "API");

int totalLength = words.stream()
      .mapToInt(String::length)
      .sum();

System.out.println(totalLength);  // 输出: 14

这个例子展示了如何利用mapToIntsum方法计算字符串的总长度。

总结

Java 8 的Stream API为我们提供了一种简洁、强大且灵活的方式来处理集合。通过filtermapsortedcollect等操作,我们可以轻松完成各种复杂的数据处理任务,同时提高代码的可读性。Stream API不仅简化了我们对数据的操作,更是开启了函数式编程在Java中的大门。

Stream API 是Java 8引入的众多新特性中的一颗明珠,它为Java开发者提供了一个强大的工具来编写更加简洁、优雅和高效的代码。如果你还没有深入使用过Stream,不妨尝试一下,它将极大地改变你的编码方式和思维模式。


http://www.kler.cn/a/289700.html

相关文章:

  • 曹操为什么总是亲征
  • 基于Java Web的传智播客crm企业管理系统的设计与实现
  • 字节跳动Android面试题汇总及参考答案(80+面试题,持续更新)
  • Elasticsearch 实战应用:高效搜索与数据分析
  • sql server 查看io资源使用
  • 每日一练:二分查找-搜索插入位置
  • log4j 清除MDC上下文 MDC分类日志
  • 2025年最新:如何搭建java springboot音乐网站?vue前端助力,实现音乐在线分享
  • OpenStack概论和部署
  • 3142. 判断矩阵是否满足条件
  • 不同Linux主机之间,复制Conda环境【最详细教程】
  • KRTS网络模块:UDP通信
  • “智能化自动化” 架构之3:中间建模脑的领域驱动设计的“同声传译”技能
  • 在仿真数据检查器中查看数据
  • GPU版pytorch安装(win/linux)
  • 生成列(Generated Columns)概述
  • HTTP 之 Web Sockets 安全策略(十)
  • 项目技巧三
  • Python基础总结之Python中常见的迭代器介绍
  • 【PyQt6 应用程序】一键视频解说克隆场景切割版
  • Marin说PCB之闲谈设计经验之沟通
  • 【论文阅读】QUEEN: Query Unlearning against Model Extraction(2024)
  • log4j 控制台和文件输出乱码问题解决
  • VUE3 使用 <transition> 实现组件切换的过渡效果
  • ArcGIS Pro SDK (十二)布局 9 布局元数据与图框
  • 国产游戏技术的全球竞争力:挑战、机遇与创新驱动力