`
Yinny
  • 浏览: 296354 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

java 字符串split有很多坑,使用时请小心!!

阅读更多
  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);//最前面的和末尾的分隔符全部都忽略,apache commons  
  System.out.println(StringUtils.splitPreserveAllTokens(":ab:cd:ef::",":").length);//不忽略任何一个分隔符 apache commons   
输出:  
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方法:


private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens)
{
        // Performance tuned for 2.0 (JDK1.4)

        if (str == null) {
            return null;
        }
        int len = str.length();
        if (len == 0) {
            return ArrayUtils.EMPTY_STRING_ARRAY;
        }
        List list = new ArrayList();
        int i = 0, start = 0;
        boolean match = false;
        boolean lastMatch = 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(new String[list.size()]);
    }
是一个核心方法,用于拆分字符串,其中字符c表示分隔符,另外布尔变量b表示c在首尾的不同处理方式。为真,则在首位留一个""的字符串。但是在中间是没有作用的。该方法执行如下操作:
  如果字符串为null,则返回null。
  如果字符串为"",则返回""。
  用i作为指针遍历字符串,match和lastMatch分别表示遇到和最后遇到可分割的内容。
    如果字符串中第一个就遇到c,则看b的值,如果为真,则会在结果数组中存入一个""。如果没遇到,match置真,lastMatch置假,表示有要分割的内容。
    一旦遇到c,则在结果数组中输出字符串在i之前的子字符串,并把起始点调整到i之后。且match置假,lastMatch置真。
  遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符是c),则输出最后的部分(如果是后者,则会输出一个"")。



private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens)
{
        // Performance tuned for 2.0 (JDK1.4)
        // Direct code is quicker than StringTokenizer.
        // Also, StringTokenizer uses isSpace() not isWhitespace()

        if (str == null) {
            return null;
        }
        int len = str.length();
        if (len == 0) {
            return ArrayUtils.EMPTY_STRING_ARRAY;
        }
        List list = new ArrayList();
        int sizePlus1 = 1;
        int i = 0, start = 0;
        boolean match = false;
        boolean lastMatch = false;
        if (separatorChars == null) {
            // Null separator means use whitespace
            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++;
            }
        } else if (separatorChars.length() == 1) {
            // Optimise 1 character case
            char sep = 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 {
            // standard case
            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(new String[list.size()]);
    }
也是一个核心方法,用于拆分字符串,其与上一个方法的不同之处在于其分隔符用字符串表示一组字符,且增加一个max变量,表示输出的字符串数组的最大长度。另外注意该方法的b如果为真,会在首尾及中间起作用,且如果分隔符字符串长度大于1,则数组中的""会更多(根据分隔符字符的数量)。该方法执行如下操作:
  如果字符串为null,则返回null。
  如果字符串为"",则返回""。
  之后的处理分三种情况,分别是分隔符字符串为null,则默认为" ";分割符字符串长度为1;分割符字符串为普通字符串。这三种处理的不同只是在当前遍历中的字符的判断问题。
    1.利用Character.isWhitespace方法判断每个字符是否为" "。
    2.先把字符串转化为一个char,然后就和前一个splitWorker方法类似。
    3.利用indexOf方法查找当前字符是否在分隔符字符串中,然后就和前一个splitWorker方法类似。
    需要注意的是,如果输出的数组的数量已经等于max的值,则把指针直接挪到最后,等待下次遍历的时候直接跳出。同时由于lastMatch和match都置为假,最后也不会输出""了。
   遍历结束,如果match为真(到最后也没有遇到c),或者lastMatch和b同为真(最后一个字符在分隔符字符串中),则输出最后的部分(如果是后者,则会输出一个"")。


  • 大小: 146.4 KB
分享到:
评论
3 楼 MeowPass 2017-04-25  
[color=red][size=xx-large][align=center]
[flash=200,200][img][url]
[list]
[*]
引用
[u][i][b]1[color=red]1[size=xx-large]1[align=right]1[/align][/size][/color][/b][/i][/u]
[/list][/url][/img][/flash]
[/align][/size][/color]                
2 楼 li123zhe123 2016-06-08  
[list]
  • [list]
  • [*][list]
  • [*][*][list]
  • [*][*][*][list]
  • [*][*][*][*][*]
    引用
    [u][i][b][u]
    引用
    [list]
    [*][*][*][*][*][*]
    [*][*][*][*][*][/list]
    [/u][/b][/i][/u]
  • [*][*][*][/list]
  • [*][*][/list]
  • [*][/list]
  • [/list]
  • [/list]
    1 楼 a545807638 2016-01-15  
    good, String [] tt =StringUtils.splitByWholeSeparator(a,",");

    相关推荐

      java字符串练习

      总的来说,Java字符串处理涉及的方法很多,包括但不限于`split()`, `substring()`, `indexOf()`, `replace()`, `trim()`等。理解并熟练运用这些方法对于提升Java编程技能非常有帮助。对于初学者而言,通过实践上述...

      Java字符串split使用方法代码实例

      "Java字符串split使用方法代码实例" Java字符串split使用方法代码实例是 Java 编程语言中的一种常见操作,用于将一个字符串拆分成多个子字符串。下面我们将详细介绍 Java 字符串 split 使用方法代码实例。 什么是...

      java中常用字符串方法总结

      字符串对象的处理涉及很多方法,这些方法使得我们在处理文本时能实现各种功能。本文将深入探讨Java中的一些常用字符串方法,帮助你更好地理解和运用它们。 1. **创建字符串对象** 在Java中,有多种方式来创建字符...

      java中截取带汉字的字符串

      在Java编程语言中,处理包含中文字符的字符串时,经常遇到的一个问题是如何正确地截取这些字符串。如果直接按照字节(byte)来进行分割,很容易导致中文字符被截断一半,从而形成乱码。这是因为一个中文字符通常占用多...

      字符串分割

      在项目`SplitStr_Project`中,很可能包含了使用各种编程语言实现字符串分割功能的示例代码,这有助于学习和理解如何在实际项目中应用字符串分割。通过深入研究这些示例,你可以了解到不同场景下如何选择合适的分隔符...

      java字符串和数组基础共21页.pdf.zip

      Java字符串和数组是Java编程语言中的基本概念,对于任何Java开发者来说,理解和掌握它们都是至关重要的。在这21页的PDF教程中,我们很可能会深入探讨这两个核心主题。 首先,让我们来谈谈Java中的字符串。在Java中...

      Java字符串及数组操作的实例源码

      字符串与数组的结合使用在很多场景下都非常常见。例如,当需要将字符串按照特定字符分割成多个部分时,可以使用`split()`方法,它会返回一个字符串数组。反之,如果要将数组内容拼接成一个字符串,可以使用`...

      java中英文字符串处理.

      这是Java字符串安全和高效的基础。 1. **创建字符串**:你可以通过`new`关键字创建一个字符串,如`String str = new String("Hello, World!");`,或者直接用双引号创建,如`String str = "Java编程";`。 2. **子串...

      java常用字符串方法网络收集txt版

      以上只是Java字符串处理的一部分知识点,实际开发中还有很多高级用法和技巧,比如正则表达式匹配、字符串缓冲区的高效使用等,都值得深入研究。这份“java常用字符串方法网络收集txt版”资料,无疑为学习和查阅这些...

      Android split处理特殊字符

      在Java字符串中,要表示反斜杠,需要写成两个反斜杠 ("\\"),因为Java字符串内部,每个反斜杠也需要被转义。 5. "]":在正则表达式中,"]"用于表示字符类的结束。如果不转义,它会被视为字符类的一部分,可能导致...

      java常用字符串方法,网络收集,txt版

      以上只是Java中字符串操作的一部分,实际开发中还有很多其他的方法,如转换为字符数组、查找子串、截取子串等。这份"java常用字符串方法,网络收集,txt版"文档应该包含了更多实用的字符串处理技巧。学习和熟练掌握...

      Java 实例 - 字符串分割源代码-详细教程.zip

      这个详细教程应该包含了对Java字符串分割的全面介绍,从基本用法到高级技巧,帮助你更好地理解和运用这一功能。通过实践这些示例代码,你可以加深对Java字符串处理的理解,并能够灵活地解决实际编程问题。

      将字符串反转

      字符串反转的方法有很多种,这里我们将探讨几种常见的编程语言中实现这一操作的方式。 1. **Python**: 在Python中,字符串是不可变对象,这意味着我们不能直接修改已存在的字符串。不过,我们可以利用切片...

      删除字符串中的空格或将字符串的多个空格换位单个空格

      首先,我们来看一个名为`StringUtil.java`的文件,它很可能包含了一些实用的字符串处理方法。在这个文件中,我们可以预期找到用于处理空格的函数。虽然具体的实现没有给出,但通常我们可以使用几种不同的方法来实现...

      js操作字符串

      以上只是JavaScript操作字符串的一部分常见方法,实际上,字符串方法还包括很多其他功能,如查找子串的出现次数、提取子串、格式化字符串等。熟练掌握这些方法,能帮助开发者更高效地处理字符串任务。在实际编程中,...

      java用split分割字符串的一个有趣现象

      最近在项目中使用了java中的split分割字符串,发现了一个bug,充分了展示了自己对java底层的认知有很多的不足和欠缺。下面将这次的经过总结出来分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。

      字符串处理函数(9KB)

      4. **连接与拼接**:`+`运算符在很多语言中用于字符串连接,Python中的`join()`函数可以将列表元素连接成一个字符串。 5. **查找与替换**:`indexOf()`(查找子字符串的位置)、`substring()`(提取子字符串)、`...

      查找某字母在字符串中出现的次数及对应的下标

      标题提到的问题——“查找某字母在字符串中出现的次数及对应的下标”——涉及到基础的字符串处理技术,这在很多编程语言中都有相应的实现方法。本篇文章将深入探讨如何在Python、Java、C++和JavaScript等主流编程...

      截取字符串

      这在很多编程语言中都有相应的方法,比如Python的`str.replace()`,Java的`String.replace()`。 5. **边界查找**:例如,查找字符串的开头(前缀)或结尾(后缀)。这在处理文件路径、URL等时特别有用。Python的`...

    Global site tag (gtag.js) - Google Analytics