BBK#2: Find Max and Min
Don't be a Java-ish dev in Kotlin-ish world, improve your knowledge about Koltin Standard Library and write better Kotlin code. ✌🏻 If your Java dev migrating to Kotlin this will help you learn alot!
Question
: Print the Highest and Lowest number from the input string. "8 3 -5 42 -1 0 0 -9 4 7 4 -4"
Try it put yourself :
👨🏻💻👉 https://www.codewars.com/kata/554b4ac871d6813a03000035/train/kotlin
This solution requires accumulator pattern, read through my article on this it will help you out a lot!

Java-ish Solution:
Best Practice
- Parsing to Int could fail, always use safe operations and provide fallbacks .i.e instead of
toInt()
, I have usedtoIntOrNull()
and did?:
handling - Never propagate null from one scope to other, that is why
?:
handling is important.
fun highAndLow(numbers: String): String {
val numbs = numbers.split(" ")
var max = numbs.get(0).toIntOrNull() ?: -1
var min = numbs.get(0).toIntOrNull() ?: -1
numbs.forEach { num ->
val currNumb = num.toIntOrNull() ?: -1
if(currNumb > max){
max = currNumb
}
if (currNumb < min){
min = currNumb
}
}
return "${max} ${min}"
}
Cons of this solutions:
- Both
max
andmin
are mutable variable, and can be accidentally mutated anywhere within the scope ofhighAndLow()
function forEach
iterations should be used only for reading values not for mutations, here it is used to external mutation of variables outside the scope offorEach
loop. For such use cases transformation operators should be used examplemap
,reduce
etc.- Logic is over expressive
Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donation💰
Solution 2:
Using fold
checkout -> https://chetangupta.net/reduce-fold/
fun highAndLow(numbers: String): String {
val firstNumber: Int = numbers.split(" ").get(0).toIntOrNull() ?: -1
val result = numbers.split(" ")
.fold(
Pair</*max*/Int,/*min*/Int>(firstNumber,firstNumber)
){ acc, it ->
val item = it.toIntOrNull()?:-1
return@fold when{
item>acc.first -> acc.copy(first = item) // updateMax
item<acc.second -> acc.copy(second = item) // updateMin
else-> acc // do nothing..
}
}
return "${result.first} ${result.second}"
}
Pros of this solutions:
- We got rid of external mutation by getting rid of
max,min variables
- By using fold, we are reducing to the one result, mutations are scoped within the fold iteration.
Cons of this solutions:
- Still bit more Expressive code, but not real deal breaker.
Solution 3:
Using stdlib
functions of Max
and Min
https://play.kotlinlang.org/byExample/05_Collections/13_max
Note: 'max(): T?' is deprecated. Use maxOrNull instead. 'min(): T?' is deprecated. Use minOrNull instead.
fun highAndLow(numbers: String): String {
val nums = numbers.split(" ").map{it.toIntOrNull()}.filterNotNull()
val max = nums.maxOrNull()?:-1
val min = nums.minOrNull()?:-1
return "$max $min"
}
Or If you have one-Liner fetish
fun highAndLow(numbers: String) = numbers.split(' ')
.map(String::toIntOrNull)
.filterNotNull()
.let { "${it.max()} ${it.min()}" }
Puff...💨 Extra expressive-ness is gone!.
Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donation💰
Community Submission
Do check out various solution posted by the community pretty good devs write pretty badass code.
Contributed by holo
fun highAndLow(numbers:String):String{
val seq = numbers.splitToSequence(' ')
val first = seq.first().toIntOrNull()!!
val result = seq.fold(Pair(first, first)) { acc, item ->
val numb = item.toIntOrNull()
return@fold if(numb!=null){
acc.copy(first = maxOf(acc.first, numb), second = minOf(acc.second, numb))
}else{
acc
}
}
return "${result.first} ${result.second}"
}
Pros
max/min
functions iterates on the list twice (actually 3 times,split
,minOrNull
andmaxOrNull
). The fold method is much better, with only 2 iterations.splitToSequence
does not iterate on the string, it only generates a lazy sequence.- Notice that Holo used
splitToSequence(' ')
and notsplitToSequence(" ")
, that is because char split is more efficient. - To make the solution even more efficient you should replace my
acc.copy
part withwhen
expression like in solution 2. I'm leaving it like that to show thatmaxOf
andminOf
operations.
Contributed by ShahBaz

Pros
- If you use
mapNotNull
you don't have to check forfilterNotNull()
Contributed by theapache64
import kotlin.system.measureTimeMillis
measureTimeMillis {
input
.split(" ")
.map { it.toInt() }
.sorted()
.let {
println("Lowest : ${it.first()}")
println("Highest : ${it.last()}")
}
}.let {
println("Theapache64 solution took $it ms")
}
}
Pros
- Taught me how to measure the performance of the code, btw @theapache64 this approach is slower than mine 😂.
Contributed by theDroidLady|Niharika
fun main() {
println(getMinAndMax("1 2 13 41 5 hh -1 17 0 5 -1"))
}
private const val DEFAULT_MIN = -1
private const val DEFAULT_MAX = -1
fun getMinAndMax(numberString: String) : String =
numberString
.split(' ')
.mapNotNull { stringItem -> stringItem.toIntOrNull() }
.distinct()
.let { numbersList -> "${numbersList.maxOrNull() ?: DEFAULT_MAX} ${numbersList.minOrNull() ?: DEFAULT_MIN}" }
}
Pros
- Adding
distinct
make sure you are not working with same string twice - Very clean code 🥂 and battle-Tested.
Contributed by AbhishekBansal

Pros
Displaying malicious use of Regex + Functional reference
.😂
Conclusion
Aim of these articles is not hate on Java, but to help people learn various ways in which they can write same logic better and more Kotlin standard library focused way.
Hope you find it informative and if you have any feedback or post request or want to subscribe to my mailing list forms are below.
Until next time. Happy Hacking! 👩💻
Solve Next :

Solve Previous:

Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donation💰