Should equals() and compareTo() be equivalent to test for equality ??

Discussion in 'Java' started by Neroku, Jan 25, 2007.

  1. Neroku

    Neroku Guest

    Well, I know equals() and compareTo() could behave different to test
    for equality, it just depend on the way I implement them, but, Would it
    be a bad practice to rewrite equals() and compareTo() so they behave in
    the following way:

    - Two different instances of the same class hold different attribute
    values, calling equals() return false comparing both objects because
    they are not the same, but compareTo() return 0, since this is the
    sorting criteria I want (a desired attribute match).

    or even

    - Two different objects of the same class hold the same attribute
    values, this is, they are internally equals, and calling equals()
    return false because the are different instances (the references are
    not the same), but calling compareTo() return 0, since all attributes
    contain the same value.


    Thanks in Advanced
     
    Neroku, Jan 25, 2007
    #1
    1. Advertising

  2. Neroku

    Ingo Menger Guest

    On 25 Jan., 12:52, "Neroku" <> wrote:
    > Well, I know equals() and compareTo() could behave different to test
    > for equality, it just depend on the way I implement them, but, Would it
    > be a bad practice to rewrite equals() and compareTo() so they behave in
    > the following way:


    Sure. No matter how you define equality, the following should always
    hold:
    a.equals(b) == (a.compareTo(b) == 0)

    Note that certain standard classes deviate from this ideal, i.e.
    BigDecimal.
     
    Ingo Menger, Jan 25, 2007
    #2
    1. Advertising

  3. On 25 Jan 2007 03:52:19 -0800, Neroku wrote:
    > Well, I know equals() and compareTo() could behave different to test
    > for equality, it just depend on the way I implement them, but, Would it
    > be a bad practice to rewrite equals() and compareTo() so they behave in
    > the following way:


    To test for identity (i.e. reference equality), use ==, not equals().

    I would find it extremely confusing if compareTo() returned 0,
    indicating that the elements are equal in sort order, but equals()
    returned false. If the objects represent the same *value*, then they
    are *equal*.

    /gordon

    --
    [ don't email me support questions or followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
     
    Gordon Beaton, Jan 25, 2007
    #3
  4. Neroku

    Tom Hawtin Guest

    Re: Should equals() and compareTo() be equivalent to test for equality??

    Neroku wrote:
    > Well, I know equals() and compareTo() could behave different to test
    > for equality, it just depend on the way I implement them, but, Would it
    > be a bad practice to rewrite equals() and compareTo() so they behave in
    > the following way:


    The JavaDocs and I strongly recommend that compareTo be consistent with
    equals (and hashCode). In theory it shouldn't actually make any
    difference (other than for one of the concurrent collections in 1.5 (not
    1.6)). However, as a programmer, I would find it 'surprising'.

    IMO, natural ordering should be considered an implementation artifact.
    String is Comparable, for instance, but the order makes no sense. It
    sorts case sensitive, and doesn't even account for code points above
    0x10000.

    > - Two different instances of the same class hold different attribute


    The value of the fields are irrelevant. Try to think in terms of what
    the object actually represents.

    Tom Hawtin
     
    Tom Hawtin, Jan 25, 2007
    #4
  5. Neroku

    Ingo Menger Guest

    On 25 Jan., 13:08, Tom Hawtin <> wrote:

    > IMO, natural ordering should be considered an implementation artifact.
    > String is Comparable, for instance, but the order makes no sense.


    It's not supposed to.

    > It sorts case sensitive,


    Yes, that's because it's supposed to be well defined, and this means,
    for instance, that "WELL DEFINED" must be either greater or less than
    "well defined", since it's not equal. But it can't be equal, because it
    can be observed, that it's different.
    (One could make this observation impossible by assigning upper case
    letters the same code points as lower case letters, of course. I don't
    think this would not be very practical, to say the least.)

    > and doesn't even account for code points above
    > 0x10000.


    Is that so?
    That's bad, of course. But I think most people really don't care about
    those.
    After all, for many decades, it didn't account for code points above
    0xff. And it was not that bad.
     
    Ingo Menger, Jan 25, 2007
    #5
  6. Neroku

    Chris Uppal Guest

    Neroku wrote:

    > Well, I know equals() and compareTo() could behave different to test
    > for equality, it just depend on the way I implement them, but, Would it
    > be a bad practice to rewrite equals() and compareTo() so they behave in
    > the following way:
    >
    > - Two different instances of the same class hold different attribute
    > values, calling equals() return false comparing both objects because
    > they are not the same, but compareTo() return 0, since this is the
    > sorting criteria I want (a desired attribute match).


    I would say that in general it's a bad idea for compareTo() not to be
    compatible with equals(). As others have said, it's not what they'd expect to
    see, and that's always something to avoid if you can.

    There may be sufficient reasons to break that rule (though I can't think of an
    example off the top of my head). Remember that you have the option of using a
    custom Comparator for your objects instead of the natural ordering implied by
    compareTo(). If the "odd" comparison order is particularly natural (despite
    it's oddness ;-) or likely to be needed in several places, then I would make
    the special Comparator implementation a class statically nested within the main
    object class. Quite possibly the Comparator would be stateless in which case
    you could have a single, immutable, public instance of the Comparator available
    for convenient use.

    -- chris
     
    Chris Uppal, Jan 25, 2007
    #6
  7. Gordon Beaton <> wrote:
    > To test for identity (i.e. reference equality), use ==, not equals().
    >
    > I would find it extremely confusing if compareTo() returned 0,
    > indicating that the elements are equal in sort order, but equals()
    > returned false. If the objects represent the same *value*, then they
    > are *equal*.


    100% agree.

    If the originator of this threads really needs an ordering
    that is inconsistent with .equals(), there is also the path
    of deriving a class from "Comparator", and pass that
    to most of the sorting-methods offered by the Class
    library. IOW, most methods that depend on an ordering
    have an overloaded variant that accepts a separate
    Comparator.
     
    Andreas Leitgeb, Jan 25, 2007
    #7
  8. Neroku

    Tom Hawtin Guest

    Re: Should equals() and compareTo() be equivalent to test for equality??

    Ingo Menger wrote:
    >
    > On 25 Jan., 13:08, Tom Hawtin <> wrote:
    >
    >> IMO, natural ordering should be considered an implementation artifact.
    >> String is Comparable, for instance, but the order makes no sense.

    >
    > It's not supposed to.


    Yes. I'm trying to say that there is no point attempting to make the
    natural order make any sense.

    Whilst you might make a Comparator differ from equals (the JavaDocs say
    use caution), it doesn't matter with Comparable. Give it any old order.
    The natural order is for algorithms such as TreeSet, not to define an
    ordering for presentation purposes. Making compareTo give a meaningful
    result is like trying to do the same with hashCode.

    Tom Hawtin
     
    Tom Hawtin, Jan 25, 2007
    #8
  9. Neroku

    Ingo Menger Guest

    On 25 Jan., 20:38, Tom Hawtin <> wrote:
    > Ingo Menger wrote:
    >
    > > On 25 Jan., 13:08, Tom Hawtin <> wrote:

    >


    > The natural order is for algorithms such as TreeSet, not to define an
    > ordering for presentation purposes. Making compareTo give a meaningful
    > result is like trying to do the same with hashCode.


    Exactly, apart from numbers, where the meaning is the mathematical one.
     
    Ingo Menger, Jan 26, 2007
    #9
  10. Neroku

    Tom Hawtin Guest

    Re: Should equals() and compareTo() be equivalent to test for equality??

    Tor Iver Wilhelmsen wrote:
    > Gordon Beaton <> writes:
    >
    >> I would find it extremely confusing if compareTo() returned 0,
    >> indicating that the elements are equal in sort order, but equals()
    >> returned false. If the objects represent the same *value*, then they
    >> are *equal*.

    >
    > Countercase: You have a Customer class you want to sort (the function
    > of Comparable) by last name then first name. And then you get two
    > customers called Joe Jackson. But you use a persistence framework so
    > you need to use equals() and hashCode() on some unique key (like a
    > customer number). So equals() will return false for the two Joes, but
    > compareTo() will return 0.


    It's a bad idea to use natural ordering for presentation. Use a
    Comparator instead.

    If you put your customers in a TreeSet (with natural ordering), you
    wouldn't get them all back out.

    Tom Hawtin
     
    Tom Hawtin, Jan 27, 2007
    #10
  11. Gordon Beaton <> writes:

    > I would find it extremely confusing if compareTo() returned 0,
    > indicating that the elements are equal in sort order, but equals()
    > returned false. If the objects represent the same *value*, then they
    > are *equal*.


    Countercase: You have a Customer class you want to sort (the function
    of Comparable) by last name then first name. And then you get two
    customers called Joe Jackson. But you use a persistence framework so
    you need to use equals() and hashCode() on some unique key (like a
    customer number). So equals() will return false for the two Joes, but
    compareTo() will return 0.

    You could probably add a third sorting field as a "tie breaker",
    though.
     
    Tor Iver Wilhelmsen, Jan 27, 2007
    #11
  12. Tom Hawtin <> writes:

    > It's a bad idea to use natural ordering for presentation. Use a
    > Comparator instead.


    Strange when the Javadocs for Comparable and Comparator seem almost
    copy-pasted... so Comparator's intent seems to be an "outside" version
    of Comparable.

    > If you put your customers in a TreeSet (with natural ordering), you
    > wouldn't get them all back out.


    Well, a TreeSet with a Comparator has the same issue.

    The natural ordering of named objects would seem to be alphabetical.
    It's not the sorting algorithm's problem that people foolishly are
    allowed to have the same name. :)

    But a fix would be to assume this in the sorting and thus add a
    "unseen" sorting key, like the customer number in my example.
     
    Tor Iver Wilhelmsen, Jan 27, 2007
    #12
  13. Re: Should equals() and compareTo() be equivalent to test for equality??

    Tor Iver Wilhelmsen wrote:
    > Tom Hawtin <> writes:
    >
    >> It's a bad idea to use natural ordering for presentation. Use a
    >> Comparator instead.

    >
    > Strange when the Javadocs for Comparable and Comparator seem almost
    > copy-pasted... so Comparator's intent seems to be an "outside" version
    > of Comparable.
    >
    >> If you put your customers in a TreeSet (with natural ordering), you
    >> wouldn't get them all back out.

    >
    > Well, a TreeSet with a Comparator has the same issue.
    >
    > The natural ordering of named objects would seem to be alphabetical.
    > It's not the sorting algorithm's problem that people foolishly are
    > allowed to have the same name. :)
    >
    > But a fix would be to assume this in the sorting and thus add a
    > "unseen" sorting key, like the customer number in my example.


    How about the numeric case. Should BigDecimal 5 with a scale of 3 be
    greater or less than BigDecimal 5 with scale 7?

    The problem in this case is two numbers that are equal in the sense of
    having the same magnitude, but that round differently.

    Patricia
     
    Patricia Shanahan, Jan 27, 2007
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. natG
    Replies:
    5
    Views:
    409
    Chris Smith
    Dec 17, 2003
  2. Nishi Bhonsle

    compareTo() method

    Nishi Bhonsle, Jan 20, 2004, in forum: Java
    Replies:
    2
    Views:
    22,078
    Nishi Bhonsle
    Jan 21, 2004
  3. Edward A Thompson
    Replies:
    4
    Views:
    560
    Tony Morris
    Feb 11, 2004
  4. Sean Mitchell
    Replies:
    25
    Views:
    619
  5. Tomasz Wegrzanowski

    Should hash equality ignore default values ?

    Tomasz Wegrzanowski, May 7, 2007, in forum: Ruby
    Replies:
    1
    Views:
    119
    Robert Dober
    May 8, 2007
Loading...

Share This Page