2013-06-04 20 views
3

答案给出,见下面 - 士气:从来没有呼吁.split()孤独;如果你想要健全的行为,总是给它一个-1的长度参数。但不是0!Java的.split()方法的角落案例:它们是什么?

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是的,见下文.split()不遵守其合同的其他情况是什么? (再次,见下文

应答(右低于此说明性质文本)

当使用Pattern,单参数.split()方法等效于调用两参数法0如一个论点。

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

如果在阅读本文之前,您不知道braindead设计决定是什么,现在您知道了。而且这是默认行为更加危险。

解决方法是始终使用.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 
+1

你引用的Javadoc。阅读...... – wchargin

回答

6

,从同样的文档:

limit参数控制图案被施加,因此次数影响结果数组的长度。

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

的限制的默认值是确实0

public String[] split(CharSequence input) 

...

此方法的工作方式类似于与给定的输入序列调用两个参数分割法和零的极限参数。

因此,空字符串被丢弃。

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


编辑:要清除了困惑:在同一个负极限,返回数组会,根据你的推理是这样的:

[ "" , "" ] 

对于非正极限,所有尾随空字符串被删除。最后一个元素是一个空字符串,所以它被删除。然后,您有:

[ "" ] 

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

换句话说,尾随指的不是在起始字符串中追尾,而是在最后一个数组中追尾。


参见:

+0

好吧,我站在纠正的尾随空字符串。但是对于开始时的空字符串,根据javadoc的说法,没有理由将其丢弃。 – fge

+0

@fge请参阅我的编辑。 – wchargin

+0

好的,这就解释了它......简而言之,为了让'.split()'真正服从它的契约,你必须使用-1作为参数的两个参数形式。确实是一个错误... – fge

0

“的另一个子匹配该模式终止”:嗯,有一个 - 对之前的空字符串下划线(与UNDERSCORE明显匹配);

不,它不会 - 模式之前,空字符串不匹配“_”

+1

但空字符串(在开始处)_is_被匹配'_'的另一个子序列终止... – fge

相关问题