(1)當所在類不使用HashSet、Hashtable、HashMap等散列集合進行存儲的時候,可以不使用hashcode。
(2)當在HashSet、Hashtable、HashMap中使用該類時,hashcode和equals是有關系的,hashcode和equals需要同時重寫才能保證元素的唯一性。hashcode是為了提高散列結構存儲中查找的效率,在線性表中沒有作用。
==操作符比較的是值【變量(棧)內存中存放的對象的(堆)內存地址】。
equal用於比較兩個對象的值是否相同【不是比地址】。
注意:Object類中的equals方法和“==”是一樣的,沒有區別,而String類,Integer類等一些類,是重寫了equals方法,才使得equals和“==不同”。對於基礎數據類型來說,沒有重寫equals方法,故兩者是一樣。
①equals()方法:
public class BaseTypeDemo { public static void main(String[] args) { //對於基本類型的變量。"=="和"equal"的區別 int t1=57; int t2=67; int t3=124; int t4=124; //“==”對於基本數據類型,判斷兩個變量的值是否相等。 Boolean result1=(t1==t2); Boolean result2=((t1+t2)==t3); Boolean result3=(t3==t4); System.out.println("【t1==t2】"+result1); System.out.println("【(t1+t2)=t3】"+result2 ); System.out.println("【t3=t4】"+result3); //“equal”不能用於基本數據類型。只能用於類變量。對於基本數據類型要用其包裝類。 Integer i1=new Integer(t1); Integer i2=new Integer(t2); Integer i3=new Integer(t3); Integer i4=new Integer(t4); Boolean ri1=i1.equals(i2); Boolean ri2=i3.equals(i1+i2); Boolean ri3=i3.equals(i4); System.out.println("【i1.equals(i2)】"+ri1); System.out.println("【i3.equals(i1+i2)】"+ri2); System.out.println("【i3.equals(i4)】"+ri3); } } /** *運行結果 【t1==t2】false 【(t1+t2)=t3】true 【t3=t4】true 【i1.equals(i2)】false 【i3.equals(i1+i2)】true 【i3.equals(i4)】true */
String類,是重寫了equals方法,才使得equals和“==不同”。讓equals比較的值,==比較的引用地址。
public class StringDemo { public static void main(String[] args) { String str1 = "Hello"; String str2 = new String("Hello"); String str3 = str2; // 引用傳遞 System.out.println(str1 == str2); // false System.out.println(str1 == str3); // false System.out.println(str2 == str3); // true System.out.println(str1.equals(str2)); // true System.out.println(str1.equals(str3)); // true System.out.println(str2.equals(str3)); // true } }
重寫equals()方法時需要把類的字段的那些在實際對象中進行傳入比較,保證是比較的對象的“內容”。而如果不重寫此時的hashCode()的話,就會出現如果是相同的一個對象,但是我修改了這個對象的某個屬性,比如在hashMap中保存的這個對象,但是此時我再想get到它就只能返回一個空值null了,因為hash值是與對象的字段屬性相關聯的,此時由於修改了這些字段屬性,所以對應的對象的哈希值也發生了改變,再用此時的哈希值去取對象是取不到的。
package map.test; import java.util.HashMap; import java.util.Map; public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } // 測試hashCode // @Override // public boolean equals(Object obj) { // // TODO Auto-generated method stub // return true; // } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public static void main(String[] args) { Person p1 = new Person("tom", 18); Person p2 = new Person("jack", 19); Map map = new HashMap<>(); map.put(p1, "111"); map.put(p2, "2222"); // key的字段發生了改變 p1.setAge(5); System.out.println(map.get(p1)); System.out.println(map.get(p2)); } }
所以使用hashmap不能輕易地去修改key的字段值,但此時map中還是存在有三個元素,只不過用get(p1)此時只能獲取到被修改了過后的key對應的value值:但是可以看的出來p1引用都指向的是同一個對象。
public static void main(String[] args) { Person p1 = new Person("tom", 18); Person p2 = new Person("jack", 19); Map map = new HashMap<>(); map.put(p1, "111"); map.put(p2, "2222"); // key的字段發生了改變 p1.setAge(5); map.put(p1, "333"); System.out.println(map); System.out.println(map.size()); System.out.println(map.get(p1)); System.out.println(map.get(p2)); }