https://kotlinlang.org logo
Title
s

Shumilin Alexandr

04/30/2022, 8:43 PM
Hi! I have a question! class :
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {}
function:
fun test(date1: MyDate, date2: MyDate) {
    // this code should compile:
    println(date1 < date2)
}
Problem: I need to write a method for comparing MyDate objects I write a solution, it works ok
override fun compareTo(other: MyDate): Int {
    val yearDiff = year - other.year
    val monthDiff = month - other.month
    val dayDiff = dayOfMonth - other.dayOfMonth

    if (yearDiff == 0) {
        if (monthDiff == 0) {
            if (dayDiff == 0) {
                return 0
            }
        } else return monthDiff
    } else return yearDiff

    return 0;
}
and now “good” solution:
override fun compareTo(other: MyDate) = when {
    year != other.year -> year - other.year
    month != other.month -> month - other.month
    else -> dayOfMonth - other.dayOfMonth
}
i am not understand how works “good” solution? can you help me? what does mean
year != other.year -> year - other.year
c

Chris Lee

04/30/2022, 9:14 PM
`when`is similar to a switch statement - the first part (before the ->) is the criteria to match (year != other.year); the second part (after the ->) is what to do when the criteria is satisfied.
👌🏻 1
e

ephemient

05/01/2022, 1:07 AM
BTW, you would be better off writing it as
override fun compareTo(other: MyDate): Int =
    compareValuesBy(this, other, { it.year }, { it.month }, { it.dayOfMonth })
which is not only simpler, but also avoids overflow problems with
-
🆒 2
e.g.
val a = MyDate(0, 0, 0)
val b = MyDate(Int.MIN_VALUE, 0, 0)
you would expect that
a > b
, but due to
-
, your comparison will actually produce
a < b
m

Matteo Mirk

05/02/2022, 3:19 PM
About the “good” solution it works because it’s exploiting the when (analogous to Java switch, or to an if/else if/… series) in cascade: if the years are different we just need to compare them, here by subtracting, otherwise we compare the months if different, or we end up comparing the days.
e

ephemient

05/03/2022, 2:15 AM
-
isn't a good solution either way, IMO. if you don't want to use the stdlib functions, then at least
when {
    year < other.year -> -1
    year > other.year -> 1
    month < other.month -> -1
    month > other.month -> 1
    dayOfMonth < other.dayOfMonth -> -1
    dayOfMonth > other.dayOfMonth -> 1
    else -> 0
}
avoids overflow issues
n

nkiesel

05/03/2022, 4:59 AM
BTW: your "ok" solution produces the wrong result if
year
and
month
are equal but
dayOfMonth
is not
1
s

Shumilin Alexandr

05/04/2022, 7:39 AM
“ok” solution worl correctly
best solution is
compareValuesBy(this, other, { it.year }, { it.month }, { it.dayOfMonth })
imho
thanks a lot for all
n

nkiesel

05/04/2022, 8:33 AM
I agree that
compareValuesBy
is the best solution. but your "ok" is not ok: it will return
0
instead of
5
for
MyDate(2022, 1, 10).compareTo(MyDate(2022, 1, 5))
. You have to use
if (yearDiff == 0) {
        if (monthDiff == 0) {
            return dayDiff
        } else return monthDiff
    } else return yearDiff
👌🏻 1
s

Shumilin Alexandr

05/04/2022, 8:38 AM
yes, you are right! i fix code for this
override fun compareTo(other: MyDate): Int {
    val yearDiff = year - other.year
    val monthDiff = month - other.month
    val dayDiff = dayOfMonth - other.dayOfMonth

    if (yearDiff == 0) {
        if (monthDiff == 0) {
            if (dayDiff == 0) {
                return 0
            } else return dayDiff
        } else return monthDiff
    } else return yearDiff

}
and now correct
I am added else return DayDiff
e

ephemient

05/05/2022, 5:52 PM
just don't use
-
. if you really wanted to keep that structure for some reason,
val yearComparison = compareValues(year, other.year)
val monthComparison = compareValues(month, other.month)
val dayComparison = compareValues(day, other.day)
return when {
    yearComparison != 0 -> yearComparison
    monthComparison != 0 -> monthComparison
    else -> dayComparison
}
👍🏻 1