aspose file tools*
The moose likes Java in General and the fly likes Implementing hashcode method of Comparator Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Implementing hashcode method of Comparator" Watch "Implementing hashcode method of Comparator" New topic
Author

Implementing hashcode method of Comparator

Avinash Tiwari
Ranch Hand

Joined: Sep 20, 2006
Posts: 50
Hi,
As we know a comparator has equals method. Object class also has equals method. As per contract if equals method is overridden we have to override hashcode method too.
In case if we override the equals method for Comparator , do we need to override the hashcode method for comparator too.

If no , why. If yes , can there be any concerns to watch out for.

Please let know.

Thanks in advance,
Avinash


Work hard and rest not till the job is done....
Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

I think you may find something useful in this post. Also make sure you read Rob's answer in this one. It is kind of misleading when the compiler allows us to put @Override as annotation whether its a super class method which is either being overridden or the methods of an interface that your class implements.

You can only override a method which has already been defined in a super class. Interfaces only have method declarations not definitions. Comparator has no hashCode() method definition, so how will you override it? You have to implement all the methods of an interface(unless, of course, you declare the class itself abstract) while you may opt to override the methods of your super class , if the requirement is such.


~ Mansukh
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Mansukhdeep Thind wrote: . . . You can only override a method which has already been defined in a super class. Interfaces only have method declarations not definitions. Comparator has no hashCode() method definition, . . .
Nonsense.

There might not be a hashCode method in the Comparator interface, but every Comparator object is an instance of a class which implements Comparator ∴ it is a subtype of java.lang.Object ∴ it has a hashCode method. More to the point: why would you override hashCode? The only point in overriding equals() is to denote two different Comparator instances which produce the same result (i.e. they implement the same function), so you only need to override hashCode in those circumstances.
Jelle Klap
Bartender

Joined: Mar 10, 2008
Posts: 1778
    
    7

And the reason the equals() method is defined (arguably superfluously) in the Comparator interface is only to allow a type-specific restriction to be included in the API documentation:

Additionally, this method can return true only if the specified object is also a comparator and it imposes the same ordering as this comparator. Thus, comp1.equals(comp2) implies that sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) for every object reference o1 and o2.


Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.
Stuart A. Burkett
Ranch Hand

Joined: May 30, 2012
Posts: 679
Campbell Ritchie wrote:There might not be a hashCode method in the Comparator interface

Well actually there is. Any interface with no superinterface defined implicitly declares methods that match the public instance methods of the Object class. JLS 9.2
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

Avinash Tiwari wrote:In case if we override the equals method for Comparator , do we need to override the hashcode method for comparator too.

The simple answer is: you can't overrride equals() with a Comparator, because it's a totally separate interface.

Also, the two things are used for different purposes: compareTo() (ie, Comparable) and Comparators are used to order objects, whereas equals() and hashCode() are used to provide identity for them. The fact that "equals" is also a part of ordering is incidental (and often quite annoying ).

I quite understand where you're coming from though; and it may interest you to know that I've created a Hash interface that performs the same sort of function for equals() and hashCode() that Comparator does for compareTo(); and also an Orderer interface that combines the two.

Winston

Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

Campbell Ritchie wrote:
Mansukhdeep Thind wrote: . . . You can only override a method which has already been defined in a super class. Interfaces only have method declarations not definitions. Comparator has no hashCode() method definition, . . .
Nonsense.

There might not be a hashCode method in the Comparator interface, but every Comparator object is an instance of a class which implements Comparator ∴ it is a subtype of java.lang.Object ∴ it has a hashCode method. More to the point: why would you override hashCode? The only point in overriding equals() is to denote two different Comparator instances which produce the same result (i.e. they implement the same function), so you only need to override hashCode in those circumstances.


That is but obvious. Any class that implements any interface has to have all the public methods that it inherits from java.lang.Object. What part exactly did you term as non sense? The one that says:

You can only override a method which has already been defined in a super class


or the one

Interfaces only have method declarations not definitions. Comparator has no hashCode() method definition,


Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
The bit which implies that because the interface has no hash code method, the instance might not have one either. The way you wrote it, it was at best very misleading.
Mansukhdeep Thind
Ranch Hand

Joined: Jul 27, 2010
Posts: 1157

Hmm. I apologize sire. I need to improve upon my communication skills. Will be careful next time onwards.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18669
    
    8

The equals() method of Comparator is there to determine whether two Comparator objects are equal, i.e. whether they "impose the same order" (as the API documentation says). And so if you did happen to implement this method, and you planned to put your Comparator objects into a Map, then yes, just like any other class, you should override the hashCode() method to match your version of equals().

But I would expect you are extremely unlikely to do that. And I also suspect that you were thinking that the equals() method of your Comparator<T> might be used to compare two objects of type T for equality. That isn't the case, it's used to compare two Comparator objects for equality.
Avinash Tiwari
Ranch Hand

Joined: Sep 20, 2006
Posts: 50
Thanks all for such prompt and helpful responses.

In the mentioned case , what is happening is :

There is a bigger comparator ( in terms of holding data) lets say HouseComparator (comparing House object) . There is a RoomComparator (comparing room object). Now HouseComparator inturn uses RoomComparator and other sub comparators for arriving at equality of House object.

So equals method of RoomComparator gets defined. Considering this scenario , is it appropriate to define hashcode method. Or we define hashcode with a constant value across all comparators.

This seems like a nested Comparator usage and not sure in such case overriding hashcode method will achieve any purpose or not overriding will do something.

Please let know.

Thanks
Avinash
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18669
    
    8

You're just filling the room with smoke. All of that is not especially relevant.

Your RoomComparator has an equals(Object) method, as do all classes. It is only useful for comparing two RoomComparator objects, so the existence of the HouseComparator class is irrelevant to that equals(Object) method. You aren't ever going to be comparing a RoomComparator object to a HouseComparator object, because being of different classes they can't possibly be equal.

You can call that "nested" comparator usage if you like but it has nothing to do with the equals() method of the Comparator classes and it has nothing to do with whether you should override the hashCode() method. As I already said, you would do that if you wanted to store RoomComparator objects in a Map. And you would only need to override the hashCode() method if you overrode the equals(Object) method, otherwise you're just using the methods inherited from Object.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Avinash Tiwari wrote: . . . So equals method of RoomComparator gets defined. . . .
Why? You have not justified using an equals() method in the first place, since you do not appear to have two comparators which do the same thing.
Paul C is right; by using the word “nested”, you are simply creating confusion.
Avinash Tiwari
Ranch Hand

Joined: Sep 20, 2006
Posts: 50
Hi
My apologies. Maybe I didn't phrase the points correctly.
Consider a case where we have 4 comparators : A , B, C and D

What I meant is if a specific Comparator A compare method uses internally compare methods of B , C and D in its compare method.

Then overriding equals method of A and all internal comparators B , C and D is done.

In this case , overriding hashcode also needs to be done. Because if you use any code review tool like FindBugs etc it points at this and says to implement hashcode too.

Thanks,
Avinash
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Avinash Tiwari wrote:Consider a case where we have 4 comparators : A , B, C and D

What I meant is if a specific Comparator A compare method uses internally compare methods of B , C and D in its compare method.

Then overriding equals method of A and all internal comparators B , C and D is done.

Why? What's the purpose of overriding equals here?

Avinash Tiwari wrote:In this case , overriding hashcode also needs to be done. Because if you use any code review tool like FindBugs etc it points at this and says to implement hashcode too.

Yes, if you override equals, you need to override hashCode too. But we don't see why you want to override equals() here. There's a very good chance you don't need to do this at all.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18669
    
    8

I suspect that Avinash might believe that because the equals method is specifically mentioned in the API documentation for Comparator, that means that implementing Comparator somehow automatically overrides the equals method. Or that it requires overriding it. Neither of those are true, of course.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Avinash Tiwari wrote: . . .
What I meant is if a specific Comparator A compare method uses internally compare methods of B , C and D in its compare method.

Then overriding equals method of A and all internal comparators B , C and D is done. . .
No, in that case it appears that the four Comparators do different things and represent different functions and therefore there is no need to override equals and hash code.
Note what Paul C said last night.
Avinash Tiwari
Ranch Hand

Joined: Sep 20, 2006
Posts: 50
Agreed. Ideally four comparators are independent in their functioning and perform their respective tasks to complete a collective task.

However this happens to be a legacy code with their equals method overridden. With no history or background of this implementation , it is difficult to fathom the reason for this behavior.

All respective people opinions ( who have helped in this thread) are highly regarded and there are same questions unanswered but touching or removing this equals implementation can have its own risk.

So from code review tool perspective , it seems the possible way is to override the hashcode method with a constant value .

Thanks
Avinash
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Yes, that would fulfil the general contract of hashCode(). I presume you are never putting those Comparators into hash based collections. Are those equals() methods ever called?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18669
    
    8

Aha, I see I haven't understood the context for this question very well.

Avinash Tiwari wrote:However this happens to be a legacy code with their equals method overridden. With no history or background of this implementation , it is difficult to fathom the reason for this behavior.

All respective people opinions ( who have helped in this thread) are highly regarded and there are same questions unanswered but touching or removing this equals implementation can have its own risk.


Yes, don't you hate it when that happens? You don't know whether the equals() method is serving a purpose or whether it was put there because the original programmer was confused in some way (by one of the points of confusion I mentioned earlier or by something else).

I would suggest that looking at the contents of the equals() method might provide some insight into why it exists and how it decides whether two Comparators are equal. On the other hand if you don't have a lot of time to deal with this issue, then no doubt the constant-value hashCode() method would make things a bit cleaner (in some ways). Another option would be to just add a comment explaining the situation and recommending that the equals() method should be reviewed and if possible deleted when time becomes available. That assumes that the code is working in a satisfactory way (you did say it was legacy).
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Paul Clapham wrote: . . . the equals() method should be reviewed and if possible deleted when time becomes available. That assumes that the code is working in a satisfactory way (you did say it was legacy).
Does that breach the great design principle, “If it ain't broke, don't fix it”?

Try adding print statements or logging statements to the equals and hash code methods to see whether they are ever called. I think most people here think it was a mistake to put those equals methods there in the first place.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
I might even have the method throw an exception, so it will become really obvious if anyone is using it. Then test your application and see what happens. Of course, this will work better if you already have a lot of automated tests for the application. If not, you may need to start writing some.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Campbell Ritchie wrote:
Paul Clapham wrote: . . . the equals() method should be reviewed and if possible deleted when time becomes available. That assumes that the code is working in a satisfactory way (you did say it was legacy).
Does that breach the great design principle, “If it ain't broke, don't fix it”?

Maybe. But it is broken in the sense that it's causing pain and confusion in the people who need to work with it. There's a trade-off here, common when considering any refactoring: how important is it that the current code continue to function as is, with no introduction of new bugs? And how often will people need to touch this code in the future, and how much of their time will be wasted by misleading or badly written code? The answers to these questions can determine whether it's worthwhile to perform the refactoring.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
Finding out whether those equals methods are ever called is part of the process of finding whether changing anything will break anything.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Yup. And we're suggesting two different ways to find them. My way is just more aggressive.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
I see what you mean about aggressive. I only just now noticed the suggestions about an exception.
Avinash Tiwari
Ranch Hand

Joined: Sep 20, 2006
Posts: 50
Yes , its a running code. And as they say any tinkering with running code can be problematic. So far it doesn't seem to be invoking equals or being used. However can't be sure of the background on this usage of equals.
So as a safety net and precaution , overriding hashcode seems to be a safe bet and will not affect the current running anyway.

Thanks everyone for the helpful insights.

Regards,
Avinash
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39436
    
  28
You're welcome
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Implementing hashcode method of Comparator