Java .split()方法的极端情况:它们是什么?

时间:2013-06-04 04:58:22

标签: java split

答案,请参见下文 - 士气:从不单独打电话给.split();如果你想要理智的行为,总是给它一个-1的长度参数。但不是0!

javadoc for Pattern.split()声明如下:

  

此方法返回的数组包含输入序列的每个子字符串,该子字符串由与此模式匹配的另一个子序列终止,或者由输入序列的末尾终止。

见证这段代码:

private static final Pattern UNDERSCORE = Pattern.compile("_");

public static void main(final String... args)
{
    System.out.println(UNDERSCORE.split("_").length);
}

现在,引用javadoc,数组应该包含输入的子串(引用):

  • “由与此模式匹配的另一个子序列终止”:好吧,有一个 - 在下划线之前的空字符串(UNDERSCORE显然匹配);
  • 或“在输入序列结束时终止”:还有一个:在下划线后面的空字符串。

然而,上面的代码打印0。为什么?这是一个已知的错误? ( imnsho yes,见下文.split()不遵守合同的其他情况是什么? (再次,见下文

答案(右下方的解释性文字)

使用Pattern时,单参数.split()方法相当于以0为参数调用双参数方法。

这就是错误所在。如果参数为0,数组末尾的所有空字符串“向下”将从结果中删除第一个非空元素

如果在阅读本文之前,你不知道脑死亡设计的决定是什么,现在你知道了。这是默认行为更加危险。

解决方案是始终使用.split()方法的完整形式,并给它一个负长度参数。这里,选择-1。在这种情况下,.split()表现得很明智:

private static final Pattern UNDERSCORE = Pattern.compile("_");

public static void main(final String... args)
{
    System.out.println(UNDERSCORE.split("_").length);
    System.out.println(UNDERSCORE.split("__").length);
    System.out.println(UNDERSCORE.split("_x_").length);
    System.out.println(UNDERSCORE.split("_", -1).length);
    System.out.println(UNDERSCORE.split("__", -1).length);
    System.out.println(UNDERSCORE.split("_x_", -1).length);
}

输出:

0 # BUG!
0 # BUG!
2 # BUG!
2 # OK
3 # OK
3 # OK

2 个答案:

答案 0 :(得分:6)

来自相同的文档:

  

limit参数控制模式的应用次数,因此会影响结果数组的长度。

     

如果 n [限制]为零,那么模式将被应用尽可能多次,数组可以具有任何长度,并且尾随空字符串将被丢弃。

限制的默认值确实是0

public String[] split(CharSequence input)
     

...

     

此方法的工作方式就像通过调用给定输入序列和limit参数为零的双参数split方法一样。

因此,空字符串被丢弃。

如果您需要使用UNDERSCORE.split("_", -1)或任何其他负整数。


编辑:为了清除混淆:根据你的推理,返回的数组会有一个负数限制,就是:

[ "" , "" ]

如果使用非正限制,则会删除所有尾随空字符串。最后一个元素是一个空字符串,因此将其删除。然后,你有:

[ "" ]

最后一个元素也是一个空字符串,因此它也会被删除。

换句话说,尾随不是指在初始字符串中尾随,而是在最终数组中尾随。


另见:

答案 1 :(得分:0)

  

“由与此模式匹配的另一个子序列终止”:好吧,有一个 - 在下划线之前的空字符串(UNDERSCORE明显匹配);

不,它没有 - 模式之前的空字符串与'_'

不匹配