A benchmark in Kotlin (which uses Java anyway, so results are about the same), on Android, using similar approach as stated above, shows that indeed contains
is similar to indexOf
, but for some reason faster, even though it uses it.
As for regular expressions, because it creates real objects, and allows to go further, it's slower.
Sample results (time in ms) :
Contains: 0
IndexOf: 5
Matches: 45
Code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
AsyncTask.execute {
val itemsCount = 1000
val minStringLength = 1000
val maxStringLength = 1000
val list = ArrayList<String>(itemsCount)
val r = Random()
val stringToSearchFor = prepareFakeString(r, 5, 10, ALPHABET_LOWERCASE + ALPHABET_UPPERCASE + DIGITS)
for (i in 0 until itemsCount)
list.add(prepareFakeString(r, minStringLength, maxStringLength, ALPHABET_LOWERCASE + ALPHABET_UPPERCASE + DIGITS))
val resultsContains = ArrayList<Boolean>(itemsCount)
val resultsIndexOf = ArrayList<Boolean>(itemsCount)
val resultsRegEx = ArrayList<Boolean>(itemsCount)
//Contains
var start: Long = System.currentTimeMillis()
var stop: Long = System.currentTimeMillis()
for (str in list) {
resultsContains.add(str.contains(stringToSearchFor))
}
Log.d("AppLog", "Contains: " + (stop - start))
//IndexOf
start = System.currentTimeMillis()
for (str in list) {
resultsIndexOf.add(str.indexOf(stringToSearchFor) >= 0)
}
stop = System.currentTimeMillis()
Log.d("AppLog", "IndexOf: " + (stop - start))
//Matches
val regex = stringToSearchFor.toRegex()
start = System.currentTimeMillis()
for (str in list) {
resultsRegEx.add(regex.find(str) != null)
}
stop = System.currentTimeMillis()
Log.d("AppLog", "Matches: " + (stop - start))
Log.d("AppLog", "checking results...")
var foundIssue = false
for (i in 0 until itemsCount) {
if (resultsContains[i] != resultsIndexOf[i] || resultsContains[i] != resultsRegEx[i]) {
foundIssue = true
break
}
}
Log.d("AppLog", "done. All results are the same?${!foundIssue}")
}
}
companion object {
const val ALPHABET_LOWERCASE = "qwertyuiopasdfghjklzxcvbnm"
const val ALPHABET_UPPERCASE = "QWERTYUIOPASDFGHJKLZXCVBNM"
const val DIGITS = "1234567890"
fun prepareFakeString(r: Random, minLength: Int, maxLength: Int, charactersToChooseFrom: String): String {
val length = if (maxLength == minLength) maxLength else r.nextInt(maxLength - minLength) + minLength
val sb = StringBuilder(length)
for (i in 0 until length)
sb.append(charactersToChooseFrom[r.nextInt(charactersToChooseFrom.length)])
return sb.toString()
}
}
}