string.split(“\\S”) 如何工作

2022-09-03 12:43:06

我正在从Ganesh和Sharma的oracle_certified_professional_java_se_7_programmer_exams_1z0-804_and_1z0-805一书中提出一个问题。

一个问题是:

  1. 请考虑以下程序并预测输出:

      class Test {
    
        public static void main(String args[]) {
          String test = "I am preparing for OCPJP";
          String[] tokens = test.split("\\S");
          System.out.println(tokens.length);
        }
      }
    

    a) 0

    b) 5

    c) 12

    d) 16

现在我明白\S是一个正则表达式,意思是将非空格字符视为分隔符。但是我对正则表达式如何进行匹配以及拆分产生的实际令牌感到困惑。

我添加了代码来打印令牌,如下所示

for (String str: tokens){
  System.out.println("<" + str + ">");
}

我得到了以下输出

16

<>

< >

<>

< >

<>

<>

<>

<>

<>

<>

<>

<>

< >

<>

<>

< >

所以很多空字符串标记。我只是不明白这一点。

我本来会这样想,如果分隔符是非空格字符,那么在上面的文本中,所有字母字符都用作分隔符,所以如果我们匹配的标记也会导致空字符串,那么也许应该有21个标记。我只是不明白Java的正则表达式引擎是如何解决这个问题的。是否有任何正则表达式大师可以为我阐明此代码?


答案 1

从API文档复制:(粗体是我的)

public String[] split(String regex)

围绕给定正则表达式的匹配项拆分此字符串。此方法的工作方式就像调用具有给定表达式和极限参数零的双参数拆分方法一样。因此,尾随空字符串不包括在结果数组中。

例如,字符串“boo:and:foo”使用这些表达式产生以下结果:

 Regex  Result
   :    { "boo", "and", "foo" }
   o    { "b", "", ":and:f" }

检查第二个示例,其中最后2个“o”刚刚被删除:您问题的答案是子字符串被视为分隔符的集合,对于非空字符串不遵循该部分,因此该部分被修剪。"OCPJP"


答案 2

结果是16而不是21的原因是这样的,来自Split的javadoc

因此,尾随空字符串不包括在结果数组中。

这意味着,例如,如果你说

"/abc//def/ghi///".split("/")

结果将有五个元素。第一个将是 ,因为它不是尾随的空字符串;其他的将是 、 、 和 。但剩余的空字符串将从数组中删除。"""abc""""def""ghi"

在已发布的案例中:

"I am preparing for OCPJP".split("\\S")

这是一回事。由于非空格字符是分隔符,因此每个字母都是一个分隔符, OCPJP 字母基本上不计算在内,因为这些分隔符会导致尾随空字符串,然后丢弃这些字符串。因此,由于 中有 15 个字母,因此它们被视为分隔 16 个子字符串(第一个是,最后一个是 )。"I am preparing for"""" "