【问题标题】:Why is String#split(...) implemented like this? [duplicate]为什么 String#split(...) 是这样实现的? [复制]
【发布时间】:2019-12-19 22:22:51
【问题描述】:

我实际上正在开发一个需要读取文本文件的软件,该软件具有一些此处不会解释的功能。在测试我的代码时,我发现了一个异常,它似乎来自str.split("\r\n") 的实现,其中str 是文件内容的子字符串。

当我的子字符串以连续的"\r\n"(几个换行符)结尾时,该方法完全忽略了这部分。例如,如果我使用以下字符串:

"\r\nLine 1\r\n\r\nLine 2\r\n\r\n"

,我想得到下面的数组;

["", "Line 1", "", "Line 2", "", ""]

,但它返回:

["", "Line 1", "", "Line 2"]

String.split() Javadoc 只通知了这一点,没有解释:

...因此,结果数组中不包含尾随的空字符串。

我无法理解这种不对称;为什么他们忽略了最后的空字符串,而不是开头?

【问题讨论】:

标签: java arrays string split javadoc


【解决方案1】:

Javadocs 解释了它为什么会这样工作;你必须问他们为什么选择这个默认实现。为什么不按照文档调用 split(regex, n) ?就像文档暗示的那样,使用 -1 可以满足您的要求。

class Main {
  public static void main(String[] args) {
    String   s = "\r\nLine 1\r\n\r\nLine 2\r\n\r\n";
    String[] r = s.split("\\r\\n", -1);

    for (int i = 0; i < r.length; i++) {
      System.out.println("i: " + i + " = \"" + r[i] + "\"");
    }
  }
}

生产:

i: 0 = ""
i: 1 = "Line 1"
i: 2 = ""
i: 3 = "Line 2"
i: 4 = ""
i: 5 = ""

【讨论】:

    【解决方案2】:

    您错过了 doc 中解释“因此”的部分,其中指出:

    此方法的工作原理就像通过使用给定表达式和零限制参数调用两个参数 split 方法一样。

    查看引用的两个参数doc 显示

    如果 n 为非正数,则该模式将被应用尽可能多的次数,并且该数组可以具有任意长度。如果 n 为零,则该模式将被应用尽可能多的次数,数组可以有任意长度,并且尾随的空字符串将被丢弃。

    所以这不是您想要的特殊情况。改为使用负整数调用:

    str.split("\r\n", -1)
    

    目前尚不清楚为什么作者认为 0 会比 -1 更受欢迎,但这并不重要,因为存在您想要的选项。

    【讨论】:

    • 感谢您指出另一种方法 :) 但是我不明白他们为什么选择默认删除尾随空格而不是前导空格。
    • 嗯,例如,如果您正在解析 CSV,则前导空格可能更重要。我不明白的是为什么他们默认不保留尾随的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 2012-10-31
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多