java 字符串split有很多坑,使用时请小心!!
Java代码
- System.out.println(":ab:cd:ef::".split(":").length);//末尾分隔符全部忽略
- System.out.println(":ab:cd:ef::".split(":",-1).length);//不忽略任何一个分隔符
- System.out.println(StringUtils.split(":ab:cd:ef::",":").length);//最前面的和末尾的分隔符全部都忽略,apachecommons
- System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一个分隔符apachecommons
- 输出:
- 4
- 6
- 3
- 6
看了下jdk里String类的public String[] split(String regex,int limit)方法,感觉平时不太会用这方法,以为在用正则表达式来拆分时候,如果匹配到的字符是最后一个字符时,会拆分出两个空字符串,例如"o"split("o",5) or "o"split("o",-2)时候 结果是"" "" 也就是下图中红框里的内容,所以平时一般都用split(String regex)方法,其实也就等同于split(String regex,0)方法,把结尾的空字符串丢弃!
String的split方法用到的参数是一个正则式,虽然强大,但是有时候容易出错。而且string并没有提供简化版本。org.apache.commons.lang.StringUtils提供的split改变了这一状况,开始使用完整的字符串作为参数,而不是regex。同时,对类似功能的jdk版本的StringTokenizer,在内部方法splitWorker中有段注释:Direct code is quicker than StringTokenizer.也就是说,这个是更快的一个工具了~~
StringUtils里的split和splitPreserveAllTokens 底层都是调用splitWorker方法实现的
下面分别来理解下两个私有的splitWorker方法:
- privatestaticString[]splitWorker(Stringstr,charseparatorChar,booleanpreserveAllTokens)
- {
- //Performancetunedfor2.0(JDK1.4)
- if(str==null){
- returnnull;
- }
- intlen=str.length();
- if(len==0){
- returnArrayUtils.EMPTY_STRING_ARRAY;
- }
- Listlist=newArrayList();
- inti=0,start=0;
- booleanmatch=false;
- booleanlastMatch=false;
- while(i<len){
- if(str.charAt(i)==separatorChar){
- if(match||preserveAllTokens){
- list.add(str.substring(start,i));
- match=false;
- lastMatch=true;
- }
- start=++i;
- continue;
- }
- lastMatch=false;
- match=true;
- i++;
- }
- if(match||(preserveAllTokens&&lastMatch)){
- list.add(str.substring(start,i));
- }
- return(String[])list.toArray(newString[list.size()]);
- }
如果字符串为null,则返回null。
如果字符串为"",则返回""。
用i作为指针遍历字符串,match和lastMatch分别表示遇到和最后遇到可分割的内容。
如果字符串中第一个就遇到c,则看b的值,如果为真,则会在结果数组中存入一个""。如果没遇到,match置真,lastMatch置假,表示有要分割的内容。
一旦遇到c,则在结果数组中输出字符串在i之前的子字符串,并把起始点调整到i之后。且match置假,lastMatch置真。
遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符是c),则输出最后的部分(如果是后者,则会输出一个"")。
- privatestaticString[]splitWorker(Stringstr,StringseparatorChars,intmax,booleanpreserveAllTokens)
- {
- //Performancetunedfor2.0(JDK1.4)
- //DirectcodeisquickerthanStringTokenizer.
- //Also,StringTokenizerusesisSpace()notisWhitespace()
- if(str==null){
- returnnull;
- }
- intlen=str.length();
- if(len==0){
- returnArrayUtils.EMPTY_STRING_ARRAY;
- }
- Listlist=newArrayList();
- intsizePlus1=1;
- inti=0,start=0;
- booleanmatch=false;
- booleanlastMatch=false;
- if(separatorChars==null){
- //Nullseparatormeansusewhitespace
- while(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++;
- }
- }elseif(separatorChars.length()==1){
- //Optimise1charactercase
- charsep=separatorChars.charAt(0);
- while(i<len){
- if(str.charAt(i)==sep){
- 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++;
- }
- }else{
- //standardcase
- while(i<len){
- if(separatorChars.indexOf(str.charAt(i))>=0){
- 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));
- }
- return(String[])list.toArray(newString[list.size()]);
- }
如果字符串为null,则返回null。
如果字符串为"",则返回""。
之后的处理分三种情况,分别是分隔符字符串为null,则默认为" ";分割符字符串长度为1;分割符字符串为普通字符串。这三种处理的不同只是在当前遍历中的字符的判断问题。
1.利用Character.isWhitespace方法判断每个字符是否为" "。
2.先把字符串转化为一个char,然后就和前一个splitWorker方法类似。
3.利用indexOf方法查找当前字符是否在分隔符字符串中,然后就和前一个splitWorker方法类似。
需要注意的是,如果输出的数组的数量已经等于max的值,则把指针直接挪到最后,等待下次遍历的时候直接跳出。同时由于lastMatch和match都置为假,最后也不会输出""了。
遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符在分隔符字符串中),则输出最后的部分(如果是后者,则会输出一个"")。
转载 自:http://yinny.iteye.com/blog/1750210
相关推荐
正则表达式,简称为正则或regex,是一种强大的文本处理工具,广泛应用于数据验证、搜索与替换、文本分析等多个领域。它在各种编程语言中都有对应的支持,如JavaScript、Python、Java、C#等。 正则表达式的核心概念...
11. **实际应用**:如何在编程语言中使用正则表达式,如JavaScript的`match()`、`search()`、`replace()`和`split()`方法,以及Python的`re`模块。 通过阅读《正则表达式系统教程.CHM》,读者可以深入理解正则...
- 添加了 `.str.split()` 方法,支持指定分隔符进行字符串分割。 - 增加了 `.query()` 方法,方便使用 SQL-like 语法进行数据筛选。 - 引入了 `.rolling()` 方法,支持窗口操作,如移动平均等。 - **数据类型支持...
这项研究的要点在于对微流体陷阱阵列与超材料共振器的集成,以及在基本电感-电容共振模式下的电场强约束。 首先,研究中使用的微流体装置,顾名思义,是指在微米尺度上操控流体的系统。与宏观尺度的流体操作相比,...
3. **C#中的正则表达式API**:使用`Regex.IsMatch()`、`Regex.Replace()`、`Regex.Split()`等方法进行匹配、替换和分割操作。 4. **表单验证事件**:理解`Control.Validating`和`Form.ValidateChildren()`事件,...
- 如何组织和运行测试用例,以及测试结果的分析。 - 单元测试覆盖度的概念及其提升方法。 - 常见的测试陷阱及其规避策略。 ##### 第13章:性能调优与优化 性能是衡量应用质量的关键指标之一。本章将深入探讨iOS应用...
技术点82 定位input split 问题 13.2.3 调试JVM 配置 技术点83 解决任务的JVM 启动参数 13.2.4 高效调试的编码准则 技术点84 调试和错误处理 13.3 MapReduce 陷阱 技术点85 MapReduce 反模式 13.4 本...
函数参数陷阱 - `def func(a, b=[]):` 的`b`参数会在多次调用间共享,可能导致意料之外的结果。 #### 42. 字符串转列表 ```python s = "1,2,3" l = s.split(',') ``` #### 43. 字符串列表转数字列表 ```python...
`short`类型操作的陷阱 `short s1 = 1; s1 = s1 + 1;` 这段代码会引发编译错误,因为`1`是`int`类型,而`+`操作会将`short`提升为`int`,因此赋值给`short`类型时会导致类型不匹配。正确的做法是使用`+=`,这将自动...
- 字符串分割:使用`split()`方法按指定分隔符分割字符串。 - 字符串替换:使用`replace()`方法替换字符串中的字符或子串。 - **常见问题**: - 处理空字符串和null值。 - 正确使用`equals()`方法比较字符串内容...
- **字符串搜索与替换**:详细介绍Perl中字符串搜索、匹配和替换的相关函数,如`grep`、`sort`、`split`等。 - **正则表达式**:介绍Perl中强大的正则表达式功能及其在字符串处理中的应用。 ##### 第2章:数字运算 ...
可以使用`split()`方法将逗号分隔的字符串转换为数组,如`String[] arr = str.split(",")`。 ### 36. 数组与字符串的length属性 数组没有`length()`方法,但有`length`属性用于获取长度。`String`类有`length()`...
可以使用`split()`方法将逗号分隔的字符串转换成数组,例如`String[] array = str.split(",")`。 #### 36\. 数组与String的length 数组没有`length()`方法,它使用`length`属性获取长度;`String`有`length()`方法...
- 实际应用中的逻辑判断案例分析。 #### Python第12课:for循环 - **知识点**: - `for`循环的语法结构。 - 使用`range()`函数进行迭代。 - 如何遍历列表、字符串等可迭代对象。 #### Python第13课:字符串 - ...
- 循环条件的设计和常见错误分析。 ##### 9. 随机数(random) - **内容概述**:介绍如何使用Python的`random`模块生成随机数。 - **关键知识点**: - `random`模块的导入方法。 - 生成随机整数和浮点数的方法。 ...
- 函数在实际问题中的应用案例分析; - 使用函数简化代码逻辑; - 函数的调试与测试方法。 - **【Python第23课】if, elif, else** - **主要内容**:详细介绍条件语句的完整形式。 - **知识点**: - `if`、`...
网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的...