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
相关推荐
具体分析如下: split 是非常重要的字符串方法,它是join的逆方法,用来将字符串分割成序列 >>> '1+2+3+4+5'.split('+') ['1', '2', '3', '4', '5'] >>> 'usr/bin/env'.split('/') ['usr', 'bin', 'env'] >>> 'usr/...
利用python实现词法分析器,并且使用分割函数取代split
split_dos
本文档详细介绍了如何在Oracle数据库中实现像C#等其它编程语言中Split函数来拆分字符的功能。例子简单易懂,并附有详细的实现过程。
java中String类的intern、split方法的详细讲解。
非常实用的VB.NET中使用split的方法,介绍详细
JAVA_split_用法,split详解,记得好评哦
split()分割字符串 1.不同环境下的区分 Java:分割字符串不能写成split(“$”)//$为要分割的字符 Android:分割字符串需要加上中括号split(“[$]”)//$为要分割的字符 2.特殊用法–当split()分割字符串遇上特殊...
PDF Split pdf 分割工具 非常简洁
IIS补丁,解决WIN7下SPLIT函数出错
详细介绍C#中Split的用法,各种情况下用法及举例介绍
Sql in split Sql in split Sql in split Sql in split
C#中Split用法,帮助大家学习交流哈
SplitContainer带箭头收缩美化,希望使用时尽量保留原作者注释,尊重原著。
主要介绍了js使用split函数按照多个字符对字符串进行分割的方法,实例分析了split函数的使用技巧,非常具有实用价值,需要的朋友可以参考下
文件分割工具 Super Split 使用说明 一、特点 本软件最大特点是能够自动检测A盘剩余容量,自适应A盘。 二、使用方法: (1)split -xxxK filename.ext 其中“K”不能省略,“K”表示以KB为单位进行...
SplitButton 分裂按钮 WPF中制作分裂按钮的DEMO,使用很方便,制作华丽的SplitButton 分裂按钮
Java中Split的用法及注意, 本文只是大概说了一下java中split的用法,其他方面要你们去查看了。
Free software for agile handling of Trados Studio tasks.