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字符串拆分内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IDEA常用插件之代码扫描SonarLint详解

    IDEA常用插件之代码扫描SonarLint详解

    SonarLint是一款用于代码扫描的插件,可以帮助查找隐藏的bug,下载并安装插件后,右键点击项目并选择“Analyze”、“AnalyzewithSonarLint”,扫描完成后可以在下方查看报告
    2025-01-01
  • JPA之多对多查询死循环嵌套问题及解决方案

    JPA之多对多查询死循环嵌套问题及解决方案

    这篇文章主要介绍了JPA之多对多查询死循环嵌套问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • MyBatis实现批量插入数据,多重forEach循环

    MyBatis实现批量插入数据,多重forEach循环

    这篇文章主要介绍了MyBatis实现批量插入数据,多重forEach循环方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 如何使用Spring Security实现用户-角色-资源的权限控制

    如何使用Spring Security实现用户-角色-资源的权限控制

    文章介绍了如何通过SpringSecurity实现用户-角色-资源的权限管理,包括基于角色的请求控制、加载用户角色信息、角色与资源的关联等步骤,同时,提供了一些测试场景,以验证权限控制是否正确,感兴趣的朋友跟随小编一起看看吧
    2024-10-10
  • Java API如何实现向Hive批量导入数据

    Java API如何实现向Hive批量导入数据

    这篇文章主要介绍了Java API如何实现向Hive批量导入数据的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java并发编程工具类JUC之LinkedBlockingQueue链表队列

    java并发编程工具类JUC之LinkedBlockingQueue链表队列

    大家都知道LinkedBlockingQueue 队列是BlockingQueue接口的实现类,所以它具有BlockingQueue接口的一切功能特点,他还提供了两种构造函数,本文中通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-06-06
  • 解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题

    解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题

    这篇文章主要介绍了解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • java日志门面之JCL和SLF4J详解

    java日志门面之JCL和SLF4J详解

    这篇文章主要给大家介绍了关于java日志门面之JCL和SLF4J的相关资料,在系统开发过程中日志框架的选择与更换是一大挑战,日志门面的概念,如JCL和SLF4J,允许开发者面向接口编程,文中介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • Spring如何处理注解的深入理解

    Spring如何处理注解的深入理解

    这篇文章主要给大家介绍了关于Spring如何处理注解的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java中的注解具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • java分页之假分页实现简单的分页器

    java分页之假分页实现简单的分页器

    这篇文章主要介绍了java分页之假分页实现简单的分页器的相关资料,需要的朋友可以参考下
    2016-04-04

最新评论