点赞再看,动力无限 。微信搜「程序猿阿朗」 。
本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章 。
![使用 StringUtils.split 的坑](http://shimg.jingyanzongjie.com/230727/113PV3V-0.png)
文章插图
在日常的 Java 开发中,由于 JDK 未能提供足够的常用的操作类库,通常我们会引入 Apache Commons Lang 工具库或者 Google Guava 工具库简化开发过程 。两个类库都为
java.lang
API 提供了很多实用工具,比如经常使用的字符串操作,基本数值操作、时间操作、对象反射以及并发操作等 。<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency>
但是,最近在使用 Apache Commons Lang 工具库时踩了一个坑,导致程序出现了意料之外的结果 。StringUtils.split 的坑也是因为踩了这个坑,索性写下一篇文章好好介绍下Apache Commons Lang 工具库中字符串操作相关 API 。
先说坑是什么,我们都知道 String 类中到的
split
方法可以分割字符串,比如字符串 aabbccdd
根据 bc
分割的结果应该是 aab
和 cdd
才对,这样的结果也很容易验证 。String str = "aabbccdd";for (String s : str.split("bc")) {System.out.println(s);}// 结果aabcdd
可能是因为 String 类中的 split
方法的影响,我一直以为 StringUtils.split
的效果应该相同,但其实完全不同,可以试着分析下面的三个方法输出结果是什么,StringUtils 是 Commons Lang 类库中的字符串工具类 。 public static void testA() {String str = "aabbccdd";String[] resultArray = StringUtils.split(str, "bc");for (String s : resultArray) {System.out.println(s);}}
我对上面 testA 方法的预期是 aab
和 cdd
,但是实际上这个方法的运行结果是:// testA 输出aadd
可以看到 b
和 c
字母都不见了,只剩下了 a
和 b
,这是已经发现问题了,查看源码后发现 StringUtils.split
方法其实是按字符进行操作的,不会把分割字符串作为一个整体来看,返回的结果中不也会包含用于分割的字符 。验证代码:
public static void testB() {String str = "abc";String[] resultArray = StringUtils.split(str, "ac");for (String s : resultArray) {System.out.println(s);}}// testB 输出bpublic static void testC() {String str = "abcd";String[] resultArray = StringUtils.split(str, "ac");for (String s : resultArray) {System.out.println(s);}}// testC 输出bd
输出结果和预期的一致了 。StringUtils.split 源码分析点开源码一眼看下去,发现在方法注释中就已经进行提示了:返回的字符串数组中不包含分隔符 。
The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the StrTokenizer class....继续追踪源码,可以看到最终 split 分割字符串时入参有四个 。
private static String[] splitWorker(final String str, // 原字符串final String separatorChars,// 分隔符final int max,// 分割后返回前多少个结果,-1 为所有final boolean preserveAllTokens // 暂不关注) {}
根据分隔符的不同又分了三种情况 。1. 分隔符为 null
final int len = str.length();if (len == 0) {return ArrayUtils.EMPTY_STRING_ARRAY;}final List<String> list = new ArrayList<>();int sizePlus1 = 1;int i = 0;int start = 0;boolean match = false;boolean lastMatch = false;if (separatorChars == null) {// Null separator means use whitespacewhile (i < len) {if (Character.isWhitespace(str.charAt(i))) {if (match || preserveAllTokens) {lastMatch = true;if (sizePlus1++ == max) {i = len;lastMatch = false;}list.add(str.substring(start, i));match = false;}start = ++i;continue;}lastMatch = false;match = true;i++;}}// ...if (match || preserveAllTokens && lastMatch) {list.add(str.substring(start, i));}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 薇姿的精华液适合什么年龄的人使用?
- 书名号使用方法 书名号用法
- 华帝电热水器质量好吗 华帝电热水器使用教程
- 冰箱风冷无霜的优缺点 使用效果好不好
- Java Timer使用介绍
- 液晶电视机选购技巧 教你选购使用与维护电视机
- SpringBoot 常用注解的原理和使用
- 椰浆稀释用热水还是冻水
- 毛巾发黄怎么洗又干净又软
- 衣物洗过缩水怎么办