Yes, this has been proposed before. See

    https://bugs.openjdk.java.net/browse/JDK-8241056

It's not obviously a bad idea, but there are a bunch of costs that seem to counterbalance the benefits.

I think the biggest problem is that adding a bunch of default methods to a widely-implemented interface (Comparable) runs the risk of name clashes. An alternative would be to add static methods with nice names, but I'm still not sure it's worthwhile.

Perhaps the next biggest problem is that it adds a lot of clutter to the API, and it doesn't add any new abstractions, it doesn't strengthen any existing abstraction, it doesn't increase performance of anything, etc. It arguably improves readability, but it also arguably could lead to confusion.

Personally I don't find `if (object.compareTo(other) > 0)` objectionable. Just move the comparison operator between the two operands. Then again, I'm an old C hacker who grew up with `if (strcmp(a, b) > 0)` which is basically the same thing, so I'm used to it.

(Interestingly, I looked at a bunch of Java tutorial sites, and -- setting aside their mistakes -- they all talked about how to *implement* Comparable, and how use Comparable objects for sorting, but not about how to compare the return value against zero to compare two objects. The javadocs don't explain this either. So maybe we have a documentation problem.)

Named methods and their alternatives seem to be something along the lines of:

    if (object.greaterThan(other))
    if (object.isGreaterThan(other))
    if (object.gt(other))

(Choice of names deferred to a bike shed to be had at a later time.)

This is kind of ok, until we get to Comparator, which would need the same thing. Instead of

    if (c.compare(a, b) > 0)

we might want

    if (c.greaterThan(a, b))
    if (c.isGreaterThan(a, b))
    if (c.gt(a, b))

Here we have to do the same mental gymnastics of moving the operator between the operands. This doesn't seem all that helpful to me.

There's also the difference between equals() and comparesEqual() or whatever. Worse, something like isNotEquals() is *not* the inverse of equals()! I think adding such methods could increase confusion instead of reducing it.

While the idiom of comparing the return value of compareTo() against zero is pretty cryptic, I think trying to solve it by adding a bunch of named methods somewhere potentially runs into a bunch of other problems. Maybe these can be avoided, but it seems like a lot of effort for not much gain. Maybe it would be more fruitful to find better ways to teach people about the compare-against-zero idiom.

s'marks




On 4/21/22 1:15 AM, Petr Janeček wrote:
Hello,
I'm pretty sure this must have come up a few times now, but
I was unable to find a discussion anywhere, so here goes:

The `if (object.compareTo(other) > 0)` construct for Comparables,
while it works, is an annoyance to readers, and I often have to
do a double-take when seeing it, to make sure it says what I think
it says.

Did we ever consider adding human-friendly default methods
to Comparable like e.g. these (names obviously subject to change):

```java
public default boolean lessThan(T other) {
     return compareTo(other) < 0;
}

public default boolean lessThanOrEqual(T other) {
     return compareTo(other) <= 0;
}

public default boolean comparesEqual(T other) {
     return compareTo(other) == 0;
}

public default boolean greaterThanOrEqual(T other) {
     return compareTo(other) >= 0;
}

public default boolean greaterThan(T other) {
     return compareTo(other) > 0;
}
```

These are pure human convenience methods to make the code easier
to read, we do not *need* them. Still, I absolutely personally
think the simplification they'd provide is worth the cost.

Are there any problems with the proposed methods that prevent them
to ever appear? Wise from the CharSequence.isEmpty() incompatibility
(https://stuartmarks.wordpress.com/2020/09/22/incompatibilities-with-jdk-15-charsequence-isempty/)
I looked at common libraries to look up potential matches, but
did not find any. The closest thing I found was AssertJ with
isGreaterThan(), and some greaterThan() methods with two or more
parameters in some obscure libraries. Now, I'm sure there *will*
be matches somewhere, and this is a risk that needs to be assessed.
Or was it simply a "meh" feature not worth the hassle?

Thank you,
PJ

P.S. I'm not a native English speaker, so the method names are
up for a potential discussion if we agree they'd make our lives
easier. I can imagine something like `comparesLessThan` or similar
variations, too.

P.P.S. The `Comparator` interface does also come into mind as it
could take similar methods, but I did not see a clear naming
pattern there. I'm open to suggestions.

Reply via email to