java 的split 方法 处理一个字符串出现次数

Java代码  收藏代码


在java.lang包中有String.split()方法,返回是一个数组

我在应用中用到一些,给大家总结一下,仅供大家参考:

1、如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split(".");

2、如果用“|”作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.split("|");

“.”和“|”都是转义字符,必须得加"\\";

3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如,“acount=? and uu =? or n=?”,把三个都分隔出来,可以用String.split("and|or");

使用String.split方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果。 

我们看jdk doc中说明  

public String[] split(String regex)

 Splits this string around matches of the given regular expression. 

参数regex是一个 regular-expression的匹配模式而不是一个简单的String,他对一些特殊的字符可能会出现你预想不到的结果,比如测试下面的代码用竖线 | 分隔字符串,你将得不到预期的结果

 

复制代码
   String[] aa = "aaa|bbb|ccc".split("|");

    //String[] aa = "aaa|bbb|ccc".split("\\|"); 这样才能得到正确的结果

    for (int i = 0 ; i <aa.length ; i++ ) {

      System.out.println("--"+aa[i]); 

    } 
复制代码

 

用竖 * 分隔字符串运行将抛出java.util.regex.PatternSyntaxException异常,用加号 + 也是如此。

复制代码
    String[] aa = "aaa*bbb*ccc".split("*");

    //String[] aa = "aaa|bbb|ccc".split("\\*"); 这样才能得到正确的结果    

    for (int i = 0 ; i <aa.length ; i++ ) {

      System.out.println("--"+aa[i]); 

    }  
复制代码

 

显然, + * 不是有效的模式匹配规则表达式,用"\\*" "\\+"转义后即可得到正确的结果。

"|" 分隔串时虽然能够执行,但是却不是预期的目的,"\\|"转义后即可得到正确的结果。

还有如果想在串中使用"\"字符,则也需要转义.首先要表达"aaaa\bbbb"这个串就应该用"aaaa\\bbbb",如果要分隔就应该这样才能得到正确结果,

String[] aa = "aaa\\bbb\\bccc".split("\\\\");

  1.   System.out.println(":ab:cd:ef::".split(":").length);//末尾分隔符全部忽略    
  2.   System.out.println(":ab:cd:ef::".split(":",-1).length);//不忽略任何一个分隔符    
  3.   System.out.println(StringUtils.split(":ab:cd:ef::",":").length);//最前面的和末尾的分隔符全部都忽略,apache commons    
  4.   System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一个分隔符 apache commons     
  5. 输出:    
  6. 4    
  7. 6    
  8. 3    
  9. 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方法:


Java代码  收藏代码
  1. private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens)  
  2. {  
  3.         // Performance tuned for 2.0 (JDK1.4)  
  4.   
  5.         if (str == null) {  
  6.             return null;  
  7.         }  
  8.         int len = str.length();  
  9.         if (len == 0) {  
  10.             return ArrayUtils.EMPTY_STRING_ARRAY;  
  11.         }  
  12.         List list = new ArrayList();  
  13.         int i = 0, start = 0;  
  14.         boolean match = false;  
  15.         boolean lastMatch = false;  
  16.         while (i < len) {  
  17.             if (str.charAt(i) == separatorChar) {  
  18.                 if (match || preserveAllTokens) {  
  19.                     list.add(str.substring(start, i));  
  20.                     match = false;  
  21.                     lastMatch = true;  
  22.                 }  
  23.                 start = ++i;  
  24.                 continue;  
  25.             }  
  26.             lastMatch = false;  
  27.             match = true;  
  28.             i++;  
  29.         }  
  30.         if (match || (preserveAllTokens && lastMatch)) {  
  31.             list.add(str.substring(start, i));  
  32.         }  
  33.         return (String[]) list.toArray(new String[list.size()]);  
  34.     }  
是一个核心方法,用于拆分字符串,其中字符c表示分隔符,另外布尔变量b表示c在首尾的不同处理方式。为真,则在首位留一个""的字符串。但是在中间是没有作用的。该方法执行如下操作:
  如果字符串为null,则返回null。
  如果字符串为"",则返回""。
  用i作为指针遍历字符串,match和lastMatch分别表示遇到和最后遇到可分割的内容。
    如果字符串中第一个就遇到c,则看b的值,如果为真,则会在结果数组中存入一个""。如果没遇到,match置真,lastMatch置假,表示有要分割的内容。
    一旦遇到c,则在结果数组中输出字符串在i之前的子字符串,并把起始点调整到i之后。且match置假,lastMatch置真。
  遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符是c),则输出最后的部分(如果是后者,则会输出一个"")。


Java代码  收藏代码
  1. private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens)  
  2. {  
  3.         // Performance tuned for 2.0 (JDK1.4)  
  4.         // Direct code is quicker than StringTokenizer.  
  5.         // Also, StringTokenizer uses isSpace() not isWhitespace()  
  6.   
  7.         if (str == null) {  
  8.             return null;  
  9.         }  
  10.         int len = str.length();  
  11.         if (len == 0) {  
  12.             return ArrayUtils.EMPTY_STRING_ARRAY;  
  13.         }  
  14.         List list = new ArrayList();  
  15.         int sizePlus1 = 1;  
  16.         int i = 0, start = 0;  
  17.         boolean match = false;  
  18.         boolean lastMatch = false;  
  19.         if (separatorChars == null) {  
  20.             // Null separator means use whitespace  
  21.             while (i < len) {  
  22.                 if (Character.isWhitespace(str.charAt(i))) {  
  23.                     if (match || preserveAllTokens) {  
  24.                         lastMatch = true;  
  25.                         if (sizePlus1++ == max) {  
  26.                             i = len;  
  27.                             lastMatch = false;  
  28.                         }  
  29.                         list.add(str.substring(start, i));  
  30.                         match = false;  
  31.                     }  
  32.                     start = ++i;  
  33.                     continue;  
  34.                 }  
  35.                 lastMatch = false;  
  36.                 match = true;  
  37.                 i++;  
  38.             }  
  39.         } else if (separatorChars.length() == 1) {  
  40.             // Optimise 1 character case  
  41.             char sep = separatorChars.charAt(0);  
  42.             while (i < len) {  
  43.                 if (str.charAt(i) == sep) {  
  44.                     if (match || preserveAllTokens) {  
  45.                         lastMatch = true;  
  46.                         if (sizePlus1++ == max) {  
  47.                             i = len;  
  48.                             lastMatch = false;  
  49.                         }  
  50.                         list.add(str.substring(start, i));  
  51.                         match = false;  
  52.                     }  
  53.                     start = ++i;  
  54.                     continue;  
  55.                 }  
  56.                 lastMatch = false;  
  57.                 match = true;  
  58.                 i++;  
  59.             }  
  60.         } else {  
  61.             // standard case  
  62.             while (i < len) {  
  63.                 if (separatorChars.indexOf(str.charAt(i)) >= 0) {  
  64.                     if (match || preserveAllTokens) {  
  65.                         lastMatch = true;  
  66.                         if (sizePlus1++ == max) {  
  67.                             i = len;  
  68.                             lastMatch = false;  
  69.                         }  
  70.                         list.add(str.substring(start, i));  
  71.                         match = false;  
  72.                     }  
  73.                     start = ++i;  
  74.                     continue;  
  75.                 }  
  76.                 lastMatch = false;  
  77.                 match = true;  
  78.                 i++;  
  79.             }  
  80.         }  
  81.         if (match || (preserveAllTokens && lastMatch)) {  
  82.             list.add(str.substring(start, i));  
  83.         }  
  84.         return (String[]) list.toArray(new String[list.size()]);  
  85.     }  
也是一个核心方法,用于拆分字符串,其与上一个方法的不同之处在于其分隔符用字符串表示一组字符,且增加一个max变量,表示输出的字符串数组的最大长度。另外注意该方法的b如果为真,会在首尾及中间起作用,且如果分隔符字符串长度大于1,则数组中的""会更多(根据分隔符字符的数量)。该方法执行如下操作:
  如果字符串为null,则返回null。
  如果字符串为"",则返回""。
  之后的处理分三种情况,分别是分隔符字符串为null,则默认为" ";分割符字符串长度为1;分割符字符串为普通字符串。这三种处理的不同只是在当前遍历中的字符的判断问题。
    1.利用Character.isWhitespace方法判断每个字符是否为" "。
    2.先把字符串转化为一个char,然后就和前一个splitWorker方法类似。
    3.利用indexOf方法查找当前字符是否在分隔符字符串中,然后就和前一个splitWorker方法类似。
    需要注意的是,如果输出的数组的数量已经等于max的值,则把指针直接挪到最后,等待下次遍历的时候直接跳出。同时由于lastMatch和match都置为假,最后也不会输出""了。
   遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符在分隔符字符串中),则输出最后的部分(如果是后者,则会输出一个"")。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值