首页 > Java > java教程 > 正文

Java正则表达式:从混合字符串中高效提取数字序列

霞舞
发布: 2025-09-25 11:47:00
原创
848人浏览过

Java正则表达式:从混合字符串中高效提取数字序列

本文探讨了在Java中如何使用正则表达式从包含数字、字母和特殊字符的混合文本中提取数字序列。核心挑战在于,由非空白字符分隔的数字应被视为一个整体,而由空白字符分隔的数字则应视为独立的序列。文章详细介绍了两种基于Java 8及更高版本的解决方案:利用Matcher.results()配合特定正则表达式捕获数字块,以及通过Pattern.splitAsStream()按空白符分割后再处理。两种方法均结合Stream API进行高效的数据转换和提取,并提供了详细的代码示例。

引言

在数据处理和文本分析中,我们经常需要从复杂的字符串中提取特定的信息。一个常见的需求是从包含字母、数字和特殊字符的混合文本中识别并提取数字。然而,当需求变得更加精细时,例如要求将由非空白字符连接的数字视为一个连续的数字序列,而将由空白字符分隔的数字视为独立的序列,传统的正则表达式方法可能会显得力不从心。

例如,对于字符串 ds[44]%6c,我们期望提取 446。而对于 2021 ds[44]%6c,我们期望提取 2021 和 446。本教程将介绍两种基于Java的解决方案,利用正则表达式和Stream API高效地实现这一目标。

解决方案一:使用 Matcher.results() 捕获数字块 (Java 9+)

此方法通过构建一个能够捕获包含数字且两侧由零个或多个非空白字符包围的序列的正则表达式,然后利用Java 9引入的 Matcher.results() 方法来获取所有匹配项。

1. 正则表达式分析

我们将使用以下正则表达式:[^\s]*\d+[^\s]*

  • [^\s]*:匹配零个或多个非空白字符。这部分用于捕获数字左侧的非数字、非空白字符,确保它们与数字一起被视为一个整体。
  • \d+:匹配一个或多个数字。这是我们想要提取的核心数字部分。
  • [^\s]*:再次匹配零个或多个非空白字符。这部分用于捕获数字右侧的非数字、非空白字符,同样确保它们与数字一起被视为一个整体。

这个正则表达式的整体作用是捕获一个“块”,这个块中至少包含一个数字,并且整个块不包含任何空白字符。

立即学习Java免费学习笔记(深入)”;

2. 实现步骤

  1. 定义一个 Pattern 对象,编译上述正则表达式。
  2. 对输入字符串使用 Pattern.matcher() 创建 Matcher 对象。
  3. 调用 Matcher.results() 获取一个 Stream<MatchResult>。每个 MatchResult 代表一个完整的匹配项。
  4. 通过 map(MatchResult::group) 提取每个匹配项的完整字符串。
  5. 对每个提取出的字符串,使用 replaceAll("\D+", "") 移除所有非数字字符,只保留纯数字。
  6. 将纯数字字符串通过 map(Integer::valueOf) 转换为 Integer 类型。
  7. 最后,使用 toList() 将结果收集到一个 List<Integer> 中。

3. 示例代码

import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class NumberExtractor {

    // 定义一个正则表达式,用于捕获包含至少一个数字,且前后由零个或多个非空白字符包围的序列
    public static final Pattern TEXT_WITH_DIGITS = Pattern.compile("[^\s]*\d+[^\s]*");

    /**
     * 从字符串中提取符合特定规则的数字序列。
     * 数字序列由非空白字符连接时被视为一个整体,由空白字符分隔时被视为独立序列。
     *
     * @param str 待处理的输入字符串
     * @return 提取出的数字序列列表
     */
    public static List<Integer> getIntsUsingMatcherResults(String str) {
        return TEXT_WITH_DIGITS.matcher(str).results() // 获取所有匹配项的Stream<MatchResult>
            .map(MatchResult::group)                   // 提取每个匹配项的完整字符串
            .map(s -> s.replaceAll("\D+", ""))        // 移除字符串中的所有非数字字符
            .map(Integer::valueOf)                     // 将纯数字字符串转换为Integer
            .collect(Collectors.toList());             // 收集结果到List
    }

    // ... (后续将添加 main 方法和另一个解决方案)
}
登录后复制

4. 注意事项

  • 此方法需要 Java 9 或更高版本,因为 Matcher.results() 是 Java 9 中引入的。
  • 正则表达式 [^\s]*\d+[^\s]* 确保了匹配到的块内部不会包含空白字符,从而满足了由非空白字符连接的数字视为一个整体的要求。

解决方案二:使用 Pattern.splitAsStream() 按空白符分割 (Java 8+)

此方法采取不同的策略:首先根据空白字符将整个字符串分割成多个子串,然后对每个子串进行处理以提取其中的数字。

怪兽AI数字人
怪兽AI数字人

数字人短视频创作,数字人直播,实时驱动数字人

怪兽AI数字人 44
查看详情 怪兽AI数字人

1. 正则表达式分析

我们将使用以下正则表达式进行分割:\s+

  • \s+:匹配一个或多个空白字符。这将作为我们的分隔符,将字符串拆分成多个不含空白字符的片段。

2. 实现步骤

  1. 定义一个 Pattern 对象,编译正则表达式 \s+。
  2. 对输入字符串调用 Pattern.splitAsStream(str),这将生成一个 Stream<String>,其中每个元素都是按空白符分割后的子串。
  3. 处理起始空白符的边缘情况:如果输入字符串以空白符开头,splitAsStream() 会在Stream的第一个位置生成一个空字符串。为了避免这种情况,我们使用 dropWhile(String::isEmpty) 来跳过所有开头的空字符串。
  4. 对每个子串,使用 replaceAll("\D+", "") 移除所有非数字字符。
  5. 将纯数字字符串通过 map(Integer::valueOf) 转换为 Integer 类型。
  6. 最后,使用 toList() 将结果收集到一个 List<Integer> 中。

3. 示例代码

import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

// ... (NumberExtractor 类的其他部分)

public class NumberExtractor {

    // ... (getIntsUsingMatcherResults 方法)

    // 定义一个正则表达式,用于匹配一个或多个空白字符,作为分割符
    public static final Pattern WHITE_SPACES = Pattern.compile("\s+");

    /**
     * 从字符串中提取符合特定规则的数字序列。
     * 该方法首先按空白符分割字符串,然后从每个片段中提取数字。
     *
     * @param str 待处理的输入字符串
     * @return 提取出的数字序列列表
     */
    public static List<Integer> getIntsUsingSplitAsStream(String str) {
        return WHITE_SPACES.splitAsStream(str)      // 按空白符分割字符串,生成Stream<String>
            .dropWhile(String::isEmpty)             // 跳过开头的空字符串(如果存在,例如字符串以空白符开头)
            .map(s -> s.replaceAll("\D+", ""))    // 移除每个片段中的所有非数字字符
            .map(Integer::valueOf)                  // 将纯数字字符串转换为Integer
            .collect(Collectors.toList());         // 收集结果到List
    }

    public static void main(String[] args) {
        System.out.println("--- 使用 Matcher.results() ---");
        System.out.println("ds[44]%6c -> " + getIntsUsingMatcherResults("ds[44]%6c"));
        System.out.println("2021 ds[44]%6c -> " + getIntsUsingMatcherResults("2021 ds[44]%6c"));
        System.out.println("  abc 123 def 456   -> " + getIntsUsingMatcherResults("  abc 123 def 456   "));
        System.out.println("no_digits_here -> " + getIntsUsingMatcherResults("no_digits_here"));
        System.out.println("only_42 -> " + getIntsUsingMatcherResults("only_42"));
        System.out.println("mixed123_456_chars -> " + getIntsUsingMatcherResults("mixed123_456_chars"));


        System.out.println("
--- 使用 Pattern.splitAsStream() ---");
        System.out.println("ds[44]%6c -> " + getIntsUsingSplitAsStream("ds[44]%6c"));
        System.out.println("2021 ds[44]%6c -> " + getIntsUsingSplitAsStream("2021 ds[44]%6c"));
        System.out.println("  abc 123 def 456   -> " + getIntsUsingSplitAsStream("  abc 123 def 456   "));
        System.out.println("no_digits_here -> " + getIntsUsingSplitAsStream("no_digits_here"));
        System.out.println("only_42 -> " + getIntsUsingSplitAsStream("only_42"));
        System.out.println("mixed123_456_chars -> " + getIntsUsingSplitAsStream("mixed123_456_chars"));
    }
}
登录后复制

4. 注意事项

  • 此方法需要 Java 8 或更高版本,因为 Pattern.splitAsStream() 和 Stream.dropWhile() (Java 9+) 或其他Stream操作是 Java 8/9 中引入的。dropWhile本身是Java 9引入,如果要在Java 8中使用,需要手动过滤空字符串,例如 filter(s -> !s.isEmpty())。
  • Pattern.splitAsStream() 相较于 String.split() 的优势在于,它直接生成一个Stream,避免了创建中间数组的开销,对于处理大型字符串时可能更高效。

运行结果

执行上述 main 方法,将得到如下输出:

--- 使用 Matcher.results() ---
ds[44]%6c -> [446]
2021 ds[44]%6c -> [2021, 446]
  abc 123 def 456   -> [123, 456]
no_digits_here -> []
only_42 -> [42]
mixed123_456_chars -> [123456]

--- 使用 Pattern.splitAsStream() ---
ds[44]%6c -> [446]
2021 ds[44]%6c -> [2021, 446]
  abc 123 def 456   -> [123, 456]
no_digits_here -> []
only_42 -> [42]
mixed123_456_chars -> [123456]
登录后复制

可以看到,两种方法都成功地实现了预期的数字提取逻辑。

总结

本文详细介绍了在Java中利用正则表达式和Stream API从混合字符串中提取特定数字序列的两种有效方法。

  • Matcher.results() 方法 (Java 9+):通过一个精巧的正则表达式 [^\s]*\d+[^\s]* 直接匹配不含空白字符的数字块,然后通过Stream操作清理非数字字符并转换为整数。这种方法在概念上更直接,因为它一次性捕获了符合条件的“数字单元”。
  • Pattern.splitAsStream() 方法 (Java 8+):首先利用 \s+ 正则表达式按空白符将字符串分割成多个片段,然后对每个片段进行数字提取和转换。此方法在处理以空白符开头的字符串时需要额外的 dropWhile (或 filter) 处理。

选择哪种方法取决于您的Java版本偏好以及对代码可读性的考量。两者都能高效地解决将由非空白字符连接的数字视为一个整体,而由空白字符分隔的数字视为独立序列的问题。在实际应用中,应根据具体场景和性能要求选择最合适的方案。

以上就是Java正则表达式:从混合字符串中高效提取数字序列的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号