Java实现字符串拆分的三种方法详解

 更新时间:2026年02月27日 08:52:54   作者:程序员越  
字符串拆分,看似简单的操作,背后却隐藏着性能的玄机,本文将和大家详细介绍一下三种Java实现字符串拆分的方法,有需要的小伙伴可以参考一下

字符串拆分,看似简单的操作,背后却隐藏着性能的玄机。今天,我们邀请三位顶尖高手同台竞技:String.split、StringUtils.splitByWholeSeparatorPreserveAllTokens、StringTokenizer。谁才是你项目中的最佳拍档?

第一章:三大高手简介

选手门派武功特点登场年代
String.splitJDK名门正则心法,功能强大JDK 1.4
StringUtils.splitByWholeSeparatorPreserveAllTokensApache Commons内外兼修,功能与性能并重
StringTokenizerJDK元老老而弥坚,简单纯粹JDK 1.0

第二章:巅峰对决——性能篇

2.1 性能基准测试

测试环境:JMH基准测试,拆分100万次,字符串长度100,10个字段

选手吞吐量 (ops/ms)相对性能内存分配
StringTokenizer8,20096%极少
StringUtils.splitByWholeSeparatorPreserveAllTokens7,80092%中等
String.split2,80033%较多

核心结论

  • StringTokenizer:性能之王,当之无愧的冠军
  • StringUtils:虽为第三方库,性能却远超JDK原生split
  • String.split:惨遭垫底,仅为冠军1/3的性能

2.2 为什么String.split这么慢?

关键原因:每次调用都要编译正则表达式!

// 分解String.split的成本
str.split(",") 的实际开销:

1. Pattern.compile(",")  // 编译正则,创建Pattern对象

2. Pattern.compile(...).split(str)  // 执行拆分

3. 创建临时数组  // 内存分配

4. 正则引擎匹配  // 复杂的状态机遍历

 JDK底层对单字符做了特殊处理,不用正则引擎,而使用indexOf,单字符性能显著提升

第三章:巅峰对决——功能篇

3.1 行为对比测试

测试1:连续分隔符的处理

String str = "a,,b,c";  // 两个逗号之间是空字符串

// String.split
System.out.println(Arrays.toString(str.split(",")));  
// 输出: [a, , b, c] ✅ 默认保留中间空

// StringUtils.splitByWholeSeparatorPreserveAllTokens
System.out.println(Arrays.toString(
    StringUtils.splitByWholeSeparatorPreserveAllTokens(str, ",")));  
// 输出: [a, , b, c] ✅ 保留所有空

// StringTokenizer
StringTokenizer st = new StringTokenizer(str, ",");
while(st.hasMoreTokens()) System.out.print(st.nextToken() + " ");
// 输出: a b c ❌ 空字符串被直接跳过了!

结论:StringTokenizer默认不返回空标记,这是它与众不同的地方。

测试2:末尾分隔符的处理

String str = "a,b,c,";  // 末尾有逗号

// String.split (默认)
System.out.println(Arrays.toString(str.split(",")));  
// 输出: [a, b, c] ❌ 末尾空被丢弃

// String.split (保留末尾空)
System.out.println(Arrays.toString(str.split(",", -1)));  
// 输出: [a, b, c, ] ✅ 用limit=-1保留

// StringUtils.splitByWholeSeparatorPreserveAllTokens
System.out.println(Arrays.toString(
    StringUtils.splitByWholeSeparatorPreserveAllTokens(str, ",")));  
// 输出: [a, b, c, ] ✅ 默认保留

// StringTokenizer
StringTokenizer st = new StringTokenizer(str, ",");
while(st.hasMoreTokens()) System.out.print(st.nextToken() + " ");
// 输出: a b c ❌ 末尾空被忽略

测试3:特殊分隔符的处理

String str = "a.b.c";


// String.split (需要转义)
System.out.println(Arrays.toString(str.split("\\.")));  
// 输出: [a, b, c] ✅ 但必须记得转义

// String.split (忘了转义)
System.out.println(Arrays.toString(str.split(".")));  
// 输出: [] ❌ 空数组!因为"."匹配任意字符

// StringUtils.splitByWholeSeparatorPreserveAllTokens
System.out.println(Arrays.toString(
    StringUtils.splitByWholeSeparatorPreserveAllTokens(str, ".")));  
// 输出: [a, b, c] ✅ 不用转义,直接使用

// StringTokenizer
StringTokenizer st = new StringTokenizer(str, ".");
while(st.hasMoreTokens()) System.out.print(st.nextToken() + " ");
// 输出: a b c ✅ 也不用转义

测试4:多字符分隔符

String str = "a--b--c";


// String.split
System.out.println(Arrays.toString(str.split("--")));  
// 输出: [a, b, c] ✅ 支持,但"--"是正则,特殊场景需要转义

// StringUtils.splitByWholeSeparatorPreserveAllTokens
System.out.println(Arrays.toString(
    StringUtils.splitByWholeSeparatorPreserveAllTokens(str, "--")));  
// 输出: [a, b, c] ✅ 原生支持多字符,且不涉及正则

// StringTokenizer
StringTokenizer st = new StringTokenizer(str, "--");
while(st.hasMoreTokens()) System.out.print(st.nextToken() + " ");
// 输出: a b c ❌ 注意:这是按'-'拆分,不是按"--"!

3.2 功能对比总表

特性String.splitStringUtils.xxxStringTokenizer
保留中间空标记✅ 支持✅ 支持❌ 不支持
保留末尾空标记需limit=-1✅ 默认保留❌ 不支持
正则表达式支持✅ 强大❌ 不支持❌ 不支持
多字符分隔符✅ 支持(正则)✅ 原生支持❌ 视为字符集
特殊字符转义必须转义无需转义无需转义
null输入抛NPE返回null抛NPE
返回类型String[]String[]Enumeration

第四章:终极总结

4.1 三大高手定位

选手定位适用场景不适用场景
String.split全能选手日常开发、需要正则性能敏感
StringUtils.xxx平衡大师需要保留空标记、多字符分隔符正则表达式匹配
StringTokenizer元老级大文件处理、遗留系统api陈旧,功能匮乏,不在推荐使用

4.2 如何选择

如果你不需要正则,大多数场景直接用:StringUtils

String[] result = StringUtils.splitByWholeSeparatorPreserveAllTokens(str, ",");

如果你需要正则能力:String.split 或 Pattern

String[] result = str.split("\\s+");  // 按空白符拆分

如果你仅处理很简单的文本,追求极致性能:StringTokenizer

StringTokenizer st = new StringTokenizer(str, ",");

4.3 面试官最爱问的问题

Q1:StringUtils.splitByWholeSeparatorPreserveAllTokens为什么比String.split快?

A:因为它使用普通字符串查找(indexOf),不涉及正则表达式,避免了编译开销。同时它一次性分配内存,不像StringTokenizer那样懒加载。

Q2:StringTokenizer现在还推荐使用吗?

A:除非你在维护遗留系统,或者明确需要它"不返回空标记"的特性,否则不建议在新代码中使用。它的API太古老,不支持现代Java特性,而且行为与主流方法不一致。

Q3:如果我要解析1GB的日志文件,该用哪个?

A:StringTokenizer或手写indexOf。因为它们都是流式处理,不会一次性创建大数组。String.split会创建一个大数组,可能导致内存溢出。

结束语

字符串拆分,看似简单,实则暗藏玄机。四大高手各有所长:

  • String.split:名门正派,能力全面
  • StringUtils:内外兼修,平衡之道
  • StringTokenizer:老而弥坚,返璞归真

记住:没有绝对的最好,只有最合适。理解了它们各自的优势和局限,你就能在任何场景下做出明智的决策。

到此这篇关于Java实现字符串拆分的三种方法详解的文章就介绍到这了,更多相关Java字符串拆分内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis 枚举映射的实现示例

    MyBatis 枚举映射的实现示例

    本文主要介绍了MyBatis 枚举映射的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-06-06
  • Java创建型设计模式之建造者模式详解

    Java创建型设计模式之建造者模式详解

    建造者模式是Java中一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程分解为多个简单对象的构建过程,本文将详细介绍Java中的建造者模式,包括它的定义、结构、实现方法以及应用场景等方面,希望对大家有所帮助
    2023-05-05
  • Go Java算法之从英文中重建数字示例详解

    Go Java算法之从英文中重建数字示例详解

    这篇文章主要为大家介绍了Go Java算法之从英文中重建数字示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • SpringBoot集成P6Spy实现SQL日志的记录详解

    SpringBoot集成P6Spy实现SQL日志的记录详解

    P6Spy是一个框架,它可以无缝地拦截和记录数据库活动,而无需更改现有应用程序的代码。一般我们使用的比较多的是使用p6spy打印我们最后执行的sql语句
    2022-11-11
  • java 线程方法join简单用法实例总结

    java 线程方法join简单用法实例总结

    这篇文章主要介绍了java 线程方法join简单用法,结合实例形式总结分析了Java线程join方法的功能、原理及使用技巧,需要的朋友可以参考下
    2019-11-11
  • SpringBoot切面实现token权限校验详解

    SpringBoot切面实现token权限校验详解

    这篇文章主要介绍了SpringBoot切面实现token权限校验详解,要实现权限校验,首先数据表和实体类上需要有权限字段,我的表中permission和gender是通过外键约束permission表和gender表实现枚举的,因为可拓展性更好,需要的朋友可以参考下
    2024-01-01
  • 剑指Offer之Java算法习题精讲链表与字符串及数组

    剑指Offer之Java算法习题精讲链表与字符串及数组

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • Java强制转化示例代码详解

    Java强制转化示例代码详解

    这篇文章主要介绍了Java编程语言中的类型转换,包括基本类型之间的强制类型转换和引用类型的强制类型转换,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-03-03
  • Java AOP实现自定义滑动窗口限流器方法详解

    Java AOP实现自定义滑动窗口限流器方法详解

    这篇文章主要介绍了Java AOP实现自定义滑动窗口限流器方法,其中滑动窗口算法弥补了计数器算法的不足,滑动窗口算法把间隔时间划分成更小的粒度,当更小粒度的时间间隔过去后,把过去的间隔请求数减掉,再补充一个空的时间间隔,需要的朋友可以参考下
    2022-07-07
  • Java中BigDecimal使用注意避坑指南

    Java中BigDecimal使用注意避坑指南

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算,下面这篇文章主要给大家介绍了关于Java中BigDecimal使用注意避坑的相关资料,需要的朋友可以参考下
    2023-02-02

最新评论