Java .split 方法匹配空字符串奇怪的行为

Java .split method matches empty string weird behaviour

我想从字符序列(即:字母和数字)中获取数字列表。所以我写了这段代码:

class A {
  public static void main(String[] args) {
    String msg = "aa811b22";
    String[] numbers = msg.split("\D+");
    for (int i = 0; i < numbers.length; i++) {
      System.out.println(">" + numbers[i] + "<");
    }

  }
}

超乎想象地运行...:[=​​23=]

 $ java A
><
>811<
>22<

好吧,所以它以某种方式匹配空字符串...我向自己解释说 ""(空字符串)实际上匹配 NON DIGIT MATCHER 的正则表达式,所以 \D+。没有什么不是数字......对吧? (然而...为什么它只返回1个空字符串?任何字符串中都有无限(∞)个空字符串)

为了确保自己,我尝试从上面给出的字符串中提取单词:

class A {
  public static void main(String[] args) {
    String msg = "aa811b22";
    String[] words = msg.split("\d+");
    for (int i = 0; i < words.length; i++) {
      System.out.println(">" + words[i] + "<");
    }

  }
}

这实际上打印了我所期望的(没有返回空字符串):

 $ run A
>aa<
>b<

但是...我做了几个完全让我困惑的测试:

System.out.println("a".split("\D+").length);
#=> 0 (WHY NOT 1? Empty string shouldn't be here?!)
System.out.println("a1".split("\D+").length);
#=> 2 (So now it splits to empty string and 1)
System.out.println("1a".split("\D+").length);
#=> 1 (now it returns expected "a" string)

所以我的问题是:

不匹配空字符串。相反,它匹配字符串开头的 "aa" 作为分隔符。第一个元素为空,因为在第一个分隔符之前只有一个空字符串。相反,对于尾随定界符,没有返回空字符串,如 documentation for split():

中所述

This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.

  • 为什么要用我给出的例子拆分 return 的空字符串?

'a' 不是数字,所以 aa 是分隔符。分隔符的两边都有 return 的元素,空字符串在 a 的左边。如果分隔符是 ",",那么在字符串 ",a,b" 之外,您会期望有 3 个元素 -- """a""b"。在这里,aa 是分隔符,就像我示例中的 ,

  • 为什么 "a".split("\D+").length returns 0 ?

'a' 不是数字,所以它是一个分隔符。分隔符的存在意味着在 a 的两边有两个从原始 String 中拆分出来的子串,均为空字符串。但是,no-arg split method 会丢弃尾随的空字符串。它们都是空的,所以它们都被丢弃了,length0

  • 为什么 "a1".split("\D+").length 是 2(而不是一个)

仅丢弃尾随的空字符串,因此元素为 """1"

  • 在拆分的情况下,"1a".split("\D+").length"a1".split("\D+").length 有何不同?

"1a" 将丢弃一个尾随空字符串,但 "a1" 不会丢弃尾随空字符串(它是前导的)。