zoukankan      html  css  js  c++  java
  • 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);//最前面的和末尾的分隔符全部都忽略,apachecommons
    4. System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一个分隔符apachecommons
    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. privatestaticString[]splitWorker(Stringstr,charseparatorChar,booleanpreserveAllTokens)
    2. {
    3. //Performancetunedfor2.0(JDK1.4)
    4. if(str==null){
    5. returnnull;
    6. }
    7. intlen=str.length();
    8. if(len==0){
    9. returnArrayUtils.EMPTY_STRING_ARRAY;
    10. }
    11. Listlist=newArrayList();
    12. inti=0,start=0;
    13. booleanmatch=false;
    14. booleanlastMatch=false;
    15. while(i<len){
    16. if(str.charAt(i)==separatorChar){
    17. if(match||preserveAllTokens){
    18. list.add(str.substring(start,i));
    19. match=false;
    20. lastMatch=true;
    21. }
    22. start=++i;
    23. continue;
    24. }
    25. lastMatch=false;
    26. match=true;
    27. i++;
    28. }
    29. if(match||(preserveAllTokens&&lastMatch)){
    30. list.add(str.substring(start,i));
    31. }
    32. return(String[])list.toArray(newString[list.size()]);
    33. }
    是一个核心方法,用于拆分字符串,其中字符c表示分隔符,另外布尔变量b表示c在首尾的不同处理方式。为真,则在首位留一个""的字符串。但是在中间是没有作用的。该方法执行如下操作:
    如果字符串为null,则返回null。
    如果字符串为"",则返回""。
    用i作为指针遍历字符串,match和lastMatch分别表示遇到和最后遇到可分割的内容。
    如果字符串中第一个就遇到c,则看b的值,如果为真,则会在结果数组中存入一个""。如果没遇到,match置真,lastMatch置假,表示有要分割的内容。
    一旦遇到c,则在结果数组中输出字符串在i之前的子字符串,并把起始点调整到i之后。且match置假,lastMatch置真。
    遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符是c),则输出最后的部分(如果是后者,则会输出一个"")。



    Java代码收藏代码
    1. privatestaticString[]splitWorker(Stringstr,StringseparatorChars,intmax,booleanpreserveAllTokens)
    2. {
    3. //Performancetunedfor2.0(JDK1.4)
    4. //DirectcodeisquickerthanStringTokenizer.
    5. //Also,StringTokenizerusesisSpace()notisWhitespace()
    6. if(str==null){
    7. returnnull;
    8. }
    9. intlen=str.length();
    10. if(len==0){
    11. returnArrayUtils.EMPTY_STRING_ARRAY;
    12. }
    13. Listlist=newArrayList();
    14. intsizePlus1=1;
    15. inti=0,start=0;
    16. booleanmatch=false;
    17. booleanlastMatch=false;
    18. if(separatorChars==null){
    19. //Nullseparatormeansusewhitespace
    20. while(i<len){
    21. if(Character.isWhitespace(str.charAt(i))){
    22. if(match||preserveAllTokens){
    23. lastMatch=true;
    24. if(sizePlus1++==max){
    25. i=len;
    26. lastMatch=false;
    27. }
    28. list.add(str.substring(start,i));
    29. match=false;
    30. }
    31. start=++i;
    32. continue;
    33. }
    34. lastMatch=false;
    35. match=true;
    36. i++;
    37. }
    38. }elseif(separatorChars.length()==1){
    39. //Optimise1charactercase
    40. charsep=separatorChars.charAt(0);
    41. while(i<len){
    42. if(str.charAt(i)==sep){
    43. if(match||preserveAllTokens){
    44. lastMatch=true;
    45. if(sizePlus1++==max){
    46. i=len;
    47. lastMatch=false;
    48. }
    49. list.add(str.substring(start,i));
    50. match=false;
    51. }
    52. start=++i;
    53. continue;
    54. }
    55. lastMatch=false;
    56. match=true;
    57. i++;
    58. }
    59. }else{
    60. //standardcase
    61. while(i<len){
    62. if(separatorChars.indexOf(str.charAt(i))>=0){
    63. if(match||preserveAllTokens){
    64. lastMatch=true;
    65. if(sizePlus1++==max){
    66. i=len;
    67. lastMatch=false;
    68. }
    69. list.add(str.substring(start,i));
    70. match=false;
    71. }
    72. start=++i;
    73. continue;
    74. }
    75. lastMatch=false;
    76. match=true;
    77. i++;
    78. }
    79. }
    80. if(match||(preserveAllTokens&&lastMatch)){
    81. list.add(str.substring(start,i));
    82. }
    83. return(String[])list.toArray(newString[list.size()]);
    84. }
    也是一个核心方法,用于拆分字符串,其与上一个方法的不同之处在于其分隔符用字符串表示一组字符,且增加一个max变量,表示输出的字符串数组的最大长度。另外注意该方法的b如果为真,会在首尾及中间起作用,且如果分隔符字符串长度大于1,则数组中的""会更多(根据分隔符字符的数量)。该方法执行如下操作:
    如果字符串为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
  • 相关阅读:
    boxcox1p归一化+pipeline+StackingCVRegressor
    rt-thread调度锁与关闭中断深度探究
    树莓派4最小化安装Linux
    树莓派4可以不用SD卡启动
    树莓派JTAG详细使用笔记
    树莓派上玩街机游戏
    用树莓派制作红白游戏机
    树莓派4上使用uboot+tftp调试rt-thread程序
    在window上搭建树莓派4b的RT-Thread开发环境2
    树莓派上运行RT-Thread并通过esp8266连接网络
  • 原文地址:https://www.cnblogs.com/xue88ming/p/7183020.html
Copyright © 2011-2022 走看看