如果我们有一个val txt: kotlin.String ="1;2;3;",并且希望将其拆分为数字数组,则可以尝试以下操作:
1 2
| val numbers = string.split(";".toRegex())
//gives: [1, 2, 3, ] |
CharSequence.split的结果中包含尾随的空String。
另一方面,如果我们查看Java String,则结果是不同的:
1 2
| val numbers2 = (string as java. lang. String). split(";")
//gives: [1, 2, 3] |
这次,使用java.lang.String.split,结果不包括结尾的空String。实际上,考虑到相应的JavaDoc,此行为是预期的:
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.
尽管在Kotlin的版本中,0也是此处记录的默认limit参数,但内部Kotlin在调用java.util.regex.Pattern::split时将0映射为负值-1:
1
| nativePattern.split(input, if (limit == 0) -1 else limit).asList() |
它似乎按预期工作,但我想知道为什么该语言似乎在限制Java API,因为不再提供0限制。
- 我不知道他们选择这样做的原因,但至少对我来说,感觉更直观。如果使用正则表达式,则可以改用负前瞻:;(?!$)或;(?!;*$)
-
我一直认为Java的limit语义很混乱。这是偶然的,自相矛盾的,几乎不可能记住。
该实现意味着通过传递limit = 0来实现的java.lang.String.split行为在Kotlin中丢失。实际上,从我的angular来看,为了确保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 < 0或limit >= 5),也不保留在最后的结果项中(如< 1.25)中的x25>。
在我看来,Kotlin API改善了此处的一致性:在某种意义上,没有特殊情况会丢失有关最后一个定界符的信息,后跟一个空字符串–它保留在最后一个定界符中结果项目或作为尾随的空条目。
IMO,Kotlin功能似乎更符合最小惊讶原则。相反,java.lang.String.split中的零极限看起来更像是修改方法语义的特殊值。负值也是如此,负值显然没有直观意义上的限制,并且如果不深入研究Javadoc,就不太清楚。
- 这是有道理的,因为在Kotlin中,操作结果很容易,例如通过string.split(";".toRegex()).dropLastWhile { it.isEmpty() }删除结尾的空字符串。
-
歇斯底里,此Kotlin的split是用Python中的split建模的,在其中"与自身一致"
-
我仍然对使用kotlin.String的"ab".split("")返回["","a","b",""],在JVM 7上java.lang.String返回["","a","b"]和在JVM 8上返回["a","b"]感到惊讶。 x1>从现在开始...
-
哦,快来看看voddan,它与大多数其他编程语言一致,java是错误的