KT-16661 Provide fast-path for Strings#split with single delimiter

Optimize single delimiter split when no matches is found:
Return listOf() of single element instead of adding 'this' to result
because underlying array in ArrayList is created lazily and
by default its size is 16.

Pre-size resulting list in split when limit is known.
This commit is contained in:
Vsevolod
2018-01-14 21:03:07 +03:00
committed by Ilya Gorbunov
parent 72ffbb9825
commit 2805371bdc
2 changed files with 83 additions and 5 deletions
+23 -1
View File
@@ -527,7 +527,6 @@ class StringTest {
assertEquals(listOf("test"), (+"test").split(*arrayOf<String>()), "empty list of delimiters, none matched -> entire string returned")
assertEquals(listOf("abc", "def", "123;456"), (+"abc;def,123;456").split(';', ',', limit = 3))
assertEquals(listOf("abc", "def", "123", "456"), (+"abc<BR>def<br>123<bR>456").split("<BR>", ignoreCase = true))
assertEquals(listOf("abc", "def", "123", "456"), (+"abc=-def==123=456").split("==", "=-", "="))
@@ -536,6 +535,20 @@ class StringTest {
assertEquals(listOf("", "", "b", "b", "", ""), (+"abba").split("a", ""))
}
@Test fun splitSingleDelimiter() = withOneCharSequenceArg { arg1 ->
operator fun String.unaryPlus(): CharSequence = arg1(this)
assertEquals(listOf(""), (+"").split(";"))
assertEquals(listOf("abc", "def", "123,456"), (+"abc,def,123,456").split(',', limit = 3))
assertEquals(listOf("abc", "def", "123,456"), (+"abc,def,123,456").split(",", limit = 3))
assertEquals(listOf("abc", "def", "123", "456"), (+"abc<BR>def<br>123<bR>456").split("<BR>", ignoreCase = true))
assertEquals(listOf("abc", "def<br>123<bR>456"), (+"abc<BR>def<br>123<bR>456").split("<BR>", ignoreCase = false))
assertEquals(listOf("a", "b", "c"), (+"a*b*c").split("*"))
}
@Test fun splitToLines() = withOneCharSequenceArg { arg1 ->
val string = arg1("first line\rsecond line\nthird line\r\nlast line")
assertEquals(listOf("first line", "second line", "third line", "last line"), string.lines())
@@ -545,6 +558,15 @@ class StringTest {
assertEquals(listOf(singleLine.toString()), singleLine.lines())
}
@Test fun splitIllegalLimit() = withOneCharSequenceArg("test string") { string ->
assertFailsWith<IllegalArgumentException> { string.split(*arrayOf<String>(), limit = -1) }
assertFailsWith<IllegalArgumentException> { string.split(*charArrayOf(), limit = -2) }
assertFailsWith<IllegalArgumentException> { string.split("", limit = -3) }
assertFailsWith<IllegalArgumentException> { string.split('3', limit = -4) }
assertFailsWith<IllegalArgumentException> { string.split("1", limit = -5) }
assertFailsWith<IllegalArgumentException> { string.split('4', '1', limit = -6) }
assertFailsWith<IllegalArgumentException> { string.split("5", "9", limit = -7) }
}
@Test fun indexOfAnyChar() = withOneCharSequenceArg("abracadabra") { string ->
val chars = charArrayOf('d', 'b')