Kotlin和Java String之间的区别与Regex分开

s1m*_*nw1 9 java regex string kotlin

如果我们有一个val txt: kotlin.String = "1;2;3;"并且喜欢将它拆分成数组,我们可以尝试以下方法:

val numbers = string.split(";".toRegex())
//gives: [1, 2, 3, ]
Run Code Online (Sandbox Code Playgroud)

尾随空String包含在结果中CharSequence.split.

另一方面,如果我们看一下Java String,结果是不同的:

val numbers2 = (string as java.lang.String).split(";")
//gives: [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

这次使用时java.lang.String.split,结果不包括尾随空String.这个行为实际上是给定相应的JavaDoc:

此方法的工作方式就像调用带有给定表达式和limit参数为零的双参数split方法一样.因此,结尾的空字符串不包含在结果数组中.

在科特林的版本,虽然,0也就是默认limit的文件的说法在这里,但内部科特林地图,0负的值-1时,java.util.regex.Pattern::split称为:

nativePattern.split(input, if (limit == 0) -1 else limit).asList()
Run Code Online (Sandbox Code Playgroud)

它似乎按预期工作但我想知道为什么该语言似乎限制Java API,因为0不再提供限制.

hot*_*key 11

实现意味着它是java.lang.String.split通过传递limit = 0在Kotlin中丢失而实现的行为.实际上,从我的观点来看,它被删除以实现Kotlin中可能的选项之间的一致性.

考虑一个字符串a:b:c:d:和一个模式:.

看看我们在Java中可以拥有的东西:

limit < 0[a, b, c, d, ]
limit = 0[a, b, c, d]
limit = 1[a:b:c:d:]
limit = 2[a, b:c:d:]
limit = 3[a, b, c:d:]
limit = 4[a, b, c, d:]
limit = 5[a, b, c, d, ](那张一样用limit < 0)
limit = 6[a, b, c, d, ]
...

看来,limit = 0选项是有点独特的:它具有尾随:通过附加的条目替换既不,与limit < 0limit >= 5,也没有保留在最后得到的产品(如用limit在1..4).

在我看来,Kotlin API在这里提高了一致性:在某种意义上,没有特殊情况会丢失有关最后一个分隔符后跟一个空字符串的信息 - 它作为最后一个结果项中的分隔符留在原位或者作为一个尾随的空条目.

IMO,Kotlin功能似乎更符合最不惊讶原则.java.lang.String.split相反,零限制看起来更像是修改方法语义的特殊值.负值也是如此,显然没有直观意义作为限制,如果不挖掘Javadoc就不太清楚.

  • 这是有道理的,因为在Kotlin中很容易操作结果,比如通过`string.split(";".toRegex())删除尾随的空字符串.dropLastWhile {it.isEmpty()}` (2认同)
  • 我仍然对使用kotlin.String的`“ ab” .split(“”)`如何返回`[“”,“ a”,“ b”,“”“],java.lang.String如何返回`[ JVM 7上的“”,“ a”,“ b”]`和[JVM 8]上的[[a“,” b“]`(/sf/answers/1923411871/)。从现在开始,我可能永远不会将空字符串传递给`split`。 (2认同)