Разница между Kotlin и Java String split с регулярным выражением

если у нас есть val txt: kotlin.String = "1;2;3;" и как разбить его на массив чисел, то можете попробовать следующее:

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

трейлинг-пустые String включается в результат CharSequence.split.

С другой стороны, если мы посмотрим на Java Strings, результат другой:

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

на этот раз, используя java.lang.String.split, результат не включает в себя трейлинг пустой String. Это поведение фактически предназначено, учитывая соответствующий JavaDoc:

этот метод работает так, как если бы вызывая метод разделения двух аргументов с заданным выражением и предельный аргумент нуля. конечные пустые строки не включаются в результирующий массив.

в версии Котлина, однако,0 также по умолчанию limit аргументов, документированных здесь, но внутренне Котлин карты 0 при отрицательном значении -1, когда java.util.regex.Pattern::split is под названием:

nativePattern.split(input, if (limit == 0) -1 else limit).asList()

кажется, что он работает по назначению, но мне интересно, почему язык, похоже, ограничивает API Java с предела 0 не предусмотрено.

1 ответов


реализация подразумевает, что это поведение java.lang.String.split достигнуто путем передачи limit = 0 это потеряно в Котлине. На самом деле, с моей точки зрения, он был удален для достижения согласованности между возможными вариантами в Котлине.

рассмотрим строку 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, не сохраняется в последнем результирующем элементе (как с limit в 1..4).

мне кажется, что API Kotlin улучшает согласованность здесь: нет специального случая, который в некотором смысле теряет информацию о последнем разделителе, за которым следует пустая строка-она остается на месте либо как разделитель в последнем результирующем элементе, либо как конечная пустая запись.

IMO, функция Котлина, кажется, лучше подходит принцип наименьшего удивления. Нулевой предел в java.lang.String.split, напротив, больше похоже на специальное значение, изменяющее семантику метода. И отрицательные значения, что явно не поняли как ограничения и не совсем ясно, не копаясь в Javadoc.