Java “为什么?”;“拆分”;在空字符串上返回非空数组?

Java “为什么?”;“拆分”;在空字符串上返回非空数组?,java,scala,Java,Scala,空字符串上的拆分返回大小为1的数组: scala> "".split(',') res1: Array[String] = Array("") 请考虑这将返回空数组: scala> ",,,,".split(',') res2: Array[String] = Array() 请解释:)拆分空字符串将返回空字符串作为第一个元素。如果在目标字符串中找不到分隔符,您将得到一个大小为1的数组,该数组保存原始字符串,即使它是空的。在所有编程语言中,我知道空字符串仍然是有效字符串。因此,使

空字符串上的拆分返回大小为1的数组:

scala> "".split(',')
res1: Array[String] = Array("")
请考虑这将返回空数组:

scala> ",,,,".split(',')
res2: Array[String] = Array()

请解释:)

拆分空字符串将返回空字符串作为第一个元素。如果在目标字符串中找不到分隔符,您将得到一个大小为1的数组,该数组保存原始字符串,即使它是空的。

在所有编程语言中,我知道空字符串仍然是有效字符串。因此,使用任何分隔符进行拆分将总是返回单个元素数组,其中元素是空白字符串。如果它是一个空(非空)字符串,那么这将是一个不同的问题。

原因与

",test" split ','


将返回大小为2的数组。第一个匹配之前的所有内容都将作为第一个元素返回。

如果将一个橙色分割零次,则正好有一个部分-橙色。

“a”。分割(“,”)
->
“a”
因此
”.split(“,”)
->

Java和Scala split方法按如下两个步骤操作:

  • 首先,按分隔符拆分字符串。自然的结果是,如果字符串不包含分隔符,则返回仅包含输入字符串的单例数组
  • 其次,删除所有最右边的空字符串。这就是原因。
    “,”.split(“,”)
    返回空数组
根据这一点,
“”.split(“,”
的结果应该是一个空数组,因为第二步是这样的,对吗

应该是这样。不幸的是,这是一个人为引入的极端情况。这是不好的,但至少在
java.util.regex.Pattern
中记录了它,如果您记得查看文档:

对于n==0,结果与n<0相同,除了尾随的空字符串 不会被退回(请注意,输入本身是 空字符串是特殊的,如上所述,并且limit参数 此处不适用。)

解决方案1:始终将-1作为第二个参数传递 因此,我建议您始终将
n==-1
作为第二个参数传递(这将跳过上面的第二步),除非您明确知道要实现什么/您确定空字符串不是您的程序将作为输入获得的内容

解决方案2:使用番石榴拆分器类 如果你已经在你的项目中使用番石榴,你可以试试这个类。它有一个非常丰富的API,使您的代码非常容易理解

Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"
无论好坏,此行为都是从Java继承的…
Scala不会覆盖
字符串
原语中的定义

请注意,您可以:

limit参数控制应用阵列的次数,因此会影响结果阵列的长度。如果限制n大于零,则模式最多应用n-1次,数组长度不大于n,数组的最后一个条目将包含最后一个匹配分隔符之外的所有输入。如果n为非正,则图案将被应用尽可能多的次数,并且阵列可以具有任意长度。如果n为零,则将尽可能多次应用该模式,数组可以有任何长度,并且将丢弃尾随的空字符串

i、 e.您可以设置
limit=-1
以获取(所有?)其他语言的行为:

@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")

@ ",a,,b,,".split(",", -1)  // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")

众所周知,Java行为是:

至少从Java5到Java8可以观察到上述行为

尝试更改在中拆分空字符串时返回空数组的行为。然而,当它在不同的地方引起倒退时,它很快又恢复了。这一变化从未进入最初的Java8版本

注意:split方法从一开始就不是用Java编写的(它是),但实际上至少从1.4开始就有了(例如,参见circa 2002)。我还在调查


现在还不清楚的是,为什么Java一开始就选择了它(我的怀疑是,它最初是“edge case”中的一个疏忽/错误),但现在不可撤销地融入到语言中,所以。

空字符串在拆分字符串时没有特殊的状态。您可以使用:

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())

我认为这是一个库函数,而不是语言的一部分。例如,在google guava中,您可以省略空字符串。>Iterable pieces=com.google.common.base.Splitter.on(',')。省略emptyStrings().split(“”)@Nicklamart这对我来说似乎是不言而喻的,但如果需要更多信息,您可以在Javadocs中查找
字符串
拆分
。@Raphael或Oracledatabase@Raphael,在任何其他编程语言中。拆分(“wtf”)。长度返回0。仅在JS中为1:/@DanielC.Sobral好的,那么为什么
,“split”,“
返回一个0的数组?为什么上次匹配后的所有内容都没有返回?但橙色不是空的(idk,如果这是OLUES的意思),它是橙色。可能拆分一个应该在那里但不在那里的橙色,因此您会返回一个值:一个空白XD这是一个深入的对话。这个隐喻对于
“orange”是有意义的。拆分(',')
,但显然与拆分空字符串无关。如果我把我缺少的橘子分成零份,我仍然没有橘子;我们是否将其表示为一个没有橙子的空列表,一个只有一个没有橙子的列表,一个有十二个没有橙子的列表,或者什么?这不是我们最终得到什么的问题,而是我们如何表现它。但是如果你把一本不存在的书按页数分割,你将一无所获。嗯。。。什么是
0/0
?此外,它似乎与字符串仅包含一个分隔符实例时观察到的行为不一致。在本例中,结果实际上是一个空数组:“,”.split(“,”).length==0+1,这是唯一实际引用文档并指出它不一致的答案。然而,我没有找到高点
Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())