0

0

Java中利用正则表达式和Stream API从混合字符串中高效提取数字

花韻仙語

花韻仙語

发布时间:2025-09-25 12:09:13

|

607人浏览过

|

来源于php中文网

原创

java中利用正则表达式和stream api从混合字符串中高效提取数字

本文探讨了如何使用Java中的正则表达式和Stream API,从包含数字、字母和特殊字符的混合文本中提取数字。核心挑战在于,由非空白字符连接的数字应被视为一个整体,而由空白字符分隔的数字则应分别提取。文章详细介绍了两种基于Java 8/9+ Stream API的解决方案:一种利用Matcher.results()进行模式匹配,另一种则通过Pattern.splitAsStream()按空白符分段处理,并提供了相应的代码示例和注意事项。

在处理混合字符串数据时,我们经常需要从中精确地提取出数值信息。本教程将针对一个具体场景,即从包含数字、字母、特殊字符的文本中,按照特定规则(非空白字符连接的数字视为一个整体,空白字符分隔的数字视为独立部分)提取所有数字,提供两种高效的Java实现方案。

1. 方案一:使用 Matcher.results() 进行模式匹配

此方案适用于Java 9及以上版本,它通过一个精心构造的正则表达式直接匹配符合条件的数字序列。

1.1 正则表达式解析

我们需要的正则表达式是 [^\s]*\d+[^\s]*。让我们分解一下它的含义:

  • [^\s]*:匹配零个或多个非空白字符。这允许数字前面可以有字母或特殊字符。
  • \d+:匹配一个或多个数字。这是我们想要提取的核心部分。
  • [^\s]*:再次匹配零个或多个非空白字符。这允许数字后面可以有字母或特殊字符。

这个正则表达式的整体作用是捕获一个包含至少一个数字,且可能被非空白字符包围的完整序列。由于它在遇到空白字符时会停止匹配,因此能够满足“空白字符分隔的数字视为独立部分”的要求。

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

1.2 实现步骤与代码示例

Matcher.results() 方法返回一个 Stream<MatchResult>,其中每个 MatchResult 代表一次成功的匹配。我们可以利用Stream API的链式操作来完成后续的数据清洗和转换。

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 = Pattern.compile("[^\s]*\d+[^\s]*");

    /**
     * 从字符串中提取符合特定规则的整数列表。
     * 非空白字符连接的数字被视为一个整体。
     *
     * @param str 待处理的输入字符串。
     * @return 提取到的整数列表。
     */
    public static List<Integer> getIntsUsingMatcherResults(String str) {
        return TEXT_WITH_DIGITS_PATTERN.matcher(str).results() // 获取所有匹配结果的Stream
            .map(MatchResult::group)                           // 提取每个匹配到的完整字符串
            .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("  abc123def 456 ghi789  -> " + getIntsUsingMatcherResults("  abc123def 456 ghi789  "));
    }
}

1.3 注意事项

  • 此方法要求Java 9或更高版本,因为 Matcher.results() 方法是在Java 9中引入的。
  • replaceAll("\D+", "") 是关键步骤,它确保从捕获到的字符串中只保留数字。\D 匹配任何非数字字符。

2. 方案二:基于 Pattern.splitAsStream() 的分段处理

此方案适用于Java 8及以上版本,它通过将原始字符串按空白字符分割成多个片段,然后对每个片段进行处理。

2.1 分割逻辑解析

首先,我们使用正则表达式 s+ 来分割字符串。s+ 匹配一个或多个空白字符(包括空格、制表符、换行符等)。这样,原始字符串就会被拆分成由非空白字符组成的多个子字符串。

腾讯交互翻译
腾讯交互翻译

腾讯AI Lab发布的一款AI辅助翻译产品

下载

2.2 实现步骤与代码示例

Pattern.splitAsStream() 方法返回一个 Stream<String>,其中每个元素是原始字符串中由分隔符分隔的子字符串。

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

public class NumberExtractorSplit {

    // 用于分割字符串的空白字符模式
    public static final Pattern WHITE_SPACES_PATTERN = Pattern.compile("\s+");

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

    public static void main(String[] args) {
        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("  abc123def 456 ghi789  -> " + getIntsUsingSplitAsStream("  abc123def 456 ghi789  "));
        System.out.println("   -> " + getIntsUsingSplitAsStream("   ")); // 测试全空白字符串
        System.out.println("abc -> " + getIntsUsingSplitAsStream("abc")); // 测试无数字字符串
    }
}

2.3 注意事项

  • 此方法要求Java 8或更高版本。dropWhile() 方法是在Java 9中引入的,但如果不需要处理输入字符串开头为空白字符的情况,或者可以接受一个空字符串作为结果,则在Java 8中可以省略 dropWhile 步骤。对于Java 8,如果需要处理开头空白字符,可能需要先用 trim() 或其他方式处理。
  • filter(s -> !s.isEmpty()) 是一个重要的补充,它用于处理那些在 replaceAll("\D+", "") 之后变为空字符串的片段(例如,原始片段是 "abc" )。
  • Pattern.splitAsStream() 相较于 String.split() 的优势在于它直接生成 Stream,避免了创建中间数组,在处理大量数据时可能更高效。

3. 示例与输出

为了更好地展示两种方法的实际效果,我们统一运行以下测试用例:

public class MainTest {
    public static void main(String[] args) {
        String test1 = "ds[44]%6c";
        String test2 = "2021 ds[44]%6c";
        String test3 = "  abc123def 456 ghi789  ";
        String test4 = "   "; // 全空白字符串
        String test5 = "abc"; // 无数字字符串

        System.out.println("--- 使用 Matcher.results() ---");
        System.out.println("'" + test1 + "' -> " + NumberExtractor.getIntsUsingMatcherResults(test1)); // Output: [446]
        System.out.println("'" + test2 + "' -> " + NumberExtractor.getIntsUsingMatcherResults(test2)); // Output: [2021, 446]
        System.out.println("'" + test3 + "' -> " + NumberExtractor.getIntsUsingMatcherResults(test3)); // Output: [123, 456, 789]
        System.out.println("'" + test4 + "' -> " + NumberExtractor.getIntsUsingMatcherResults(test4)); // Output: []
        System.out.println("'" + test5 + "' -> " + NumberExtractor.getIntsUsingMatcherResults(test5)); // Output: []

        System.out.println("
--- 使用 Pattern.splitAsStream() ---");
        System.out.println("'" + test1 + "' -> " + NumberExtractorSplit.getIntsUsingSplitAsStream(test1)); // Output: [446]
        System.out.println("'" + test2 + "' -> " + NumberExtractorSplit.getIntsUsingSplitAsStream(test2)); // Output: [2021, 446]
        System.out.println("'" + test3 + "' -> " + NumberExtractorSplit.getIntsUsingSplitAsStream(test3)); // Output: [123, 456, 789]
        System.out.println("'" + test4 + "' -> " + NumberExtractorSplit.getIntsUsingSplitAsStream(test4)); // Output: []
        System.out.println("'" + test5 + "' -> " + NumberExtractorSplit.getIntsUsingSplitAsStream(test5)); // Output: []
    }
}

输出结果:

--- 使用 Matcher.results() ---
'ds[44]%6c' -> [446]
'2021 ds[44]%6c' -> [2021, 446]
'  abc123def 456 ghi789  ' -> [123, 456, 789]
'   ' -> []
'abc' -> []

--- 使用 Pattern.splitAsStream() ---
'ds[44]%6c' -> [446]
'2021 ds[44]%6c' -> [2021, 446]
'  abc123def 456 ghi789  ' -> [123, 456, 789]
'   ' -> []
'abc' -> []

4. 总结与选择建议

两种方法都有效地解决了从混合字符串中提取数字的问题,并遵循了特定的分隔规则。

  • Matcher.results() (Java 9+)

    • 优点:正则表达式直接定义了要“捕获”的数字序列模式,逻辑上更直观地表达了“查找符合特定结构的数字组”。
    • 缺点:需要Java 9及以上版本。
    • 适用场景:当提取逻辑主要集中在识别特定模式的数字序列时,此方法更为直接。
  • Pattern.splitAsStream() (Java 8+)

    • 优点:利用空白字符进行分割,将问题分解为更小的、独立的片段处理,对于按分隔符处理的场景非常自然。在Java 8中可用(尽管dropWhile是Java 9特性,但可通过其他方式规避)。
    • 缺点:需要额外处理分割后可能产生的空字符串。
    • 适用场景:当核心问题是根据特定分隔符(如空白符)将字符串分解为多个逻辑单元时,此方法非常高效和简洁。

在实际开发中,您可以根据项目所使用的Java版本、个人偏好以及对代码可读性的考量来选择最合适的方案。两者都展示了Java Stream API在处理集合数据和进行转换方面的强大能力,使得代码更加简洁和富有表达力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

258

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

766

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

219

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

357

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

245

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

547

2023.12.06

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.2万人学习

Java 教程
Java 教程

共578课时 | 81.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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