Você está na página 1de 5

Use of hashCode() and equals().

Object class provides two methods hashcode() and equals() to represent the identity of an object. It is a common convention that if one method is overridden then other should also be implemented. Before explaining why, let see what the contract these two methods hold. As per the Java API documentation:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashcode() method must consistently return the same integer, provided no information used in equals() comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. If two objects are equal according to the equals(object) method, then calling the hashCode() method on each of the two objects must produce the same integer result. It is NOT required that if two objects are unequal according to the equals(Java.lang.Object) method, then calling the hashCode() method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

Now, consider an example where the key used to store the in Hashmap is an Integer. Consider that Integer class doesn't implement hashcode() method. The code would look like: map.put(new Integer(5),"Value1"); String value = (String) map.get(new Integer(5)); System.out.println(value); //Output : Value is null

Null value will be displayed since the hashcode() method returns a different hash value for the Integer object created at line 2and JVM tries to search for the object at different location. Now if the integer class has hashcode() method like: public int hashCode(){ return value; } Everytime the new Integer object is created with same integer value passed; the Integer object will return the same hash value. Once the same hash value is returned, JVM will go to the same memory address every time and if in case there are more than one objects present for the same hash value it will use equals() method to identify the correct object.

Another step of caution that needs to be taken is that while implementing the hashcode() method the fields that are present in the hashcode() should not be the one which could change the state of object. Consider the example: public class FourWheeler implements Vehicle { private String name; private int purchaseValue; private int noOfTyres; public FourWheeler(){} public FourWheeler(String name, int purchaseValue) { this.name = name; this.purchaseValue = purchaseValue; } public void setPurchaseValue(int purchaseValue) { this.purchaseValue = purchaseValue; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + purchaseValue; return result; } } FourWheeler fourWObj = new FourWheeler( Santro?,?333333); map.put(fourWObj,?Hyundai); fourWObj.setPurchaseValue( 555555)

System.out.println(map.get(fourWObj)); //Output: null We can see that inspite of passing the same object the value returned is null. This is because the hashcode() returned on evaluation will be different since the purchaseValue is set to 555555 from 333333. Though the above implementation is correct but it fails because for generating hashcode a changeable property (in this case price) is selected. To make above implementation correct we can either exclued the property or include some other property like noOfTyres and keep the logic of implementation same. Hence we can conclude that the hashcode() should contain fields that doesn't change the state of object. One compatible, but not all that useful, way to define hashCode() is like this: public int hashcode(){ return 0; } This approach will yield bad performance for the HashMap. The conclusion which can be made is that the hashcode() should(not must) return the same value if the objects are equal. If the objects are not equal then it must return different value.

Use of comparable and comparator interface


In java the element in collections can be sorted by using TreeSet or TreeMap. To sort the data elements a class needs to implement Comparator or Comparable interface. Thats why all Wrapper classes like Integer,Double and String class implements Comparable interface. A class implementing Comparable interface need to override compareTo(Object obj) method and put the logic for sorting.
The method returns an int value :-1,0,1 It will return -1 : If this object is lesser than the passed object It will return 0 : If this object is same the passed object It will return 1 : If this object is greater than the passed object

Consider a class Person.


class Person { public String name; public String lastName; public Person(String name, String lastName){ this.name=name; this.lastName=lastName; } public String getName(){ return name; } public String getLastName(){ return lastName; }

public static void main(String arg[]){ List myList = new ArrayList(); myList.add(new Person("Robert","USA")); myList.add(new Person("Andy","UK")); myList.add(new Person("Harish","India")); for(Person person : myList){ System.out.println("My name is "+person.getName()); } } } Output is : My name is Robert My name is Andy My name is Harish

But now i want that the objects to be sorted on name basis should be retrieved in sorted order. Consider a class Person.
class Person implements Comparable{ public String name; public String lastName; public Person(String name, String lastName){ this.name=name; this.lastName=lastName; } public String getName(){ return name; } public String getLastName(){ return lastName; } public int compareTo(Object obj){ Person p = (Person)obj; return this.name.compareTo(p.getName); } public static void main(String arg[]){ List myList = new ArrayList(); myList.add(new Person("Robert","USA")); myList.add(new Person("Andy","UK")); myList.add(new Person("Harish","India")); Collections.sort(myList); for(Person person : myList){ System.out.println("My name is "+person.getName()); } } } Output is : My name is Andy My name is Harish My name is Robert

Couple of things which needs to be taken in consideration: 1) Collections.sort() will sort only the collection having objects which implements either one of the comparing interface. 2) Collections.sort() will sort the same list. Comparator interface is used when an extra logic is required to sort the objects. One need to override compare(Object obj1, Object obj2) method.For example you want the list of Person object to be sorted on the basis of complete name i.e "name lastName" but also on the other hand doesnt want to change the Person class default sorting implementation or Person class is a jar so so no code modification in it can be done. First create a Custom Comparator.
public class MyCustomComparator implements Comparator{ public int compare(Object obj1, Object obj2){ Person p1 =(Person) obj1; Person p2 =(Person) ob2; String p1Name = p1.getName()+ " " +p1.getLastName(); String p2Name = p2.getName()+ " " +p2.getLastName(); return p1Name.toCompareTo(p2Name); } } // Changes made in main method of Person class. public static void main(String arg[]){ List myList = new ArrayList(); myList.add(new Person("Robert","USA")); myList.add(new Person("Robert","UK")); myList.add(new Person("Robert","India")); Collections.sort(myList new MyCustomComparator()); for(Person person : myList){ System.out.println("My name is "+person.getName() + " " + person.getLastName()); } } OutPut: My name is Robert India My name is Robert UK My name is Robert USA

Couple of things which needs to be taken in consideration: 1) For Comparator interface you need to override method compare(obj) 2) In collections.sort() the instance of Comparator need to be passed. In this example the list is sorted according to the custom Comparator created

Você também pode gostar