
在 Java 中,若需从路径类字符串(如 /good/123/bad/456)中提取所有数字,直接使用 split() 会触发多次字符串拷贝和临时对象创建;而复用预编译正则 + Long.parseLong(CharSequence, int, int, int) 可显著减少内存分配与 GC 压力,性能更优。
在 java 中,若需从路径类字符串(如 `/good/123/bad/456`)中提取所有数字,直接使用 `split()` 会触发多次字符串拷贝和临时对象创建;而复用预编译正则 + `long.parselong(charsequence, int, int, int)` 可显著减少内存分配与 gc 压力,性能更优。
当处理类似 /good/312321312/bad/3213122131 的字符串并提取其中的数字时,表面看 String.split("/|\D+") 或正则 Pattern.compile("\d+").matcher(...) 都能达成目标,但底层开销差异显著。
关键瓶颈在于 字符串切片(substring):split() 会为每个分隔符两侧生成全新 String 对象,即使你只关心其中两个数字,它仍会为 /good/、/bad/ 等非数字片段创建无用字符串——这涉及字符数组复制、对象头分配及后续 GC 回收。而正则 Matcher 仅定位起止索引(m.start() / m.end()),配合 Java 9+ 新增的 Long.parseLong(CharSequence, int, int, int) 方法,可直接解析原始字符串的指定区间,完全规避中间 String 实例。
✅ 推荐写法(高性能、低内存):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
private static final Pattern NUMBER_PATTERN = Pattern.compile("\d+");
public static long[] extractNumbers(String input) {
Matcher m = NUMBER_PATTERN.matcher(input);
LongStream.Builder builder = LongStream.builder();
while (m.find()) {
builder.add(Long.parseLong(input, m.start(), m.end(), 10));
}
return builder.build().toArray();
}⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 务必复用 Pattern 实例:Pattern.compile() 开销较大,应声明为 static final,避免每次调用都重新编译;
- Java 版本要求:Long.parseLong(CharSequence, int, int, int) 自 Java 9 引入,若项目仍在 Java 8,可退化为 Long.parseLong(m.group()),虽仍创建短字符串,但至少避免了无关片段的拷贝;
- 场景适配:若仅需前两个数字(如示例),可用短路逻辑提前终止匹配,进一步节省 CPU;
- 不要滥用 String.split():其便利性以隐式 Pattern 创建和全量 String 分割为代价,不适合高频或性能敏感路径。
总结:在追求极致性能的场景下,“定位 + 原生解析” 永远优于 “分割 + 筛选”。通过预编译正则 + 索引级数值解析,既减少堆内存压力,又提升吞吐量——尤其在日志解析、API 路径处理等高频字符串提取任务中,这一优化可带来可观的性能收益。

















