1.有如下代碼: java
class A{ public A(String str){ } } public class Test{ public static void main(String[] args) { A classa=new A("he"); A classb=new A("he"); System.out.println(classa==classb); } }
輸出是什麼?數組
答案:false多線程
即使是System.out.println(classa.equals(classb));也是false。 由於equals這個方法沒有重寫。併發
##關於重寫equals方法:this
①爲何要重寫equals方法:spa
默認equals在比較兩個對象時,是看他們是否指向同一個地址的。當一個類有本身特有的「邏輯相等」概念,好比一個People類,包含id和name兩個屬性,咱們想只要id和name同時相等的時候就斷定爲equal,可是不重寫equals方法是作不到的。
package test01; class People{ int id; String name; public People(int id,String name){ this.id=id; this.name=name; } } public class t5 { public static void main(String[] args) { People people1=new People(123,"jia"); People people2=new People(123,"jia"); System.out.println(people1.equals(people2)); } }
這樣輸出爲「false」線程
package test01; class People{ int id; String name; public People(int id,String name){ this.id=id; this.name=name; } public boolean equals(Object obj){ if(obj instanceof People){ People p=(People)obj; return p.id==id&&p.name.equals(name); } if(this==obj){ return true; } if(this==null) return false; return false; } } public class t5 { public static void main(String[] args) { People people1=new People(123,"jia"); People people2=new People(123,"jia"); System.out.println(people1.equals(people2)); } }
重寫equals方法以後,這樣的輸出爲true。code
可是看看下面一段代碼: 對象
package test01; import java.util.HashMap; import java.util.Iterator; class People{ int id; String name; public int getId() { return id; } public String getName() { return name; } public People(int id,String name){ this.id=id; this.name=name; } public boolean equals(Object obj){ if(obj instanceof People){ People p=(People)obj; return p.id==id&&p.name.equals(name); } if(this==obj){ return true; } if(this==null) return false; return false; } } class Department{ String DepartmentName; int DepartmentId; public Department(int DepartmentId,String DepartmentName){ this.DepartmentId=DepartmentId; this.DepartmentName=DepartmentName; } public String getDepartmentName() { return DepartmentName; } public int getDepartmentId() { return DepartmentId; } } public class t5 { public static void main(String[] args) { HashMap<People,Department> map=new HashMap<People,Department>(); People people1=new People(123,"jia");
Department department1=new Department(11,"FinanceDepartment");
map.put(people1,department1);
People people2=new People(123,"jia");
Department department2=new Department(12,"MarketingDepartment");blog
map.put(people2,department2); People people3=null; System.out.println(people1.equals(people2)); Iterator it=map.keySet().iterator(); while(it.hasNext()){ People tmp=(People)it.next(); System.out.println(tmp.getName()+" "+tmp.getId()+" "+map.get (tmp).getDepartmentName() +" "+map.get(tmp).getDepartmentId()); } } }
我將兩個People和Department做爲HashMap中的key和value的值,代碼中能夠看出來,people1和people2的內容是徹底相同的,那麼按照HashMap的性質,put數據進HashMap的時候當key值與map內的某一key值相同時,是將原來的value值覆蓋掉的。可是,運行的結果是
因而可知,key值徹底相同,可是並無把第一個的value值覆蓋掉。
先來看看HashMap中的put方法:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
能夠看到,在put中若是(其key的hashcod與map中key的hashcode相同,key值與map中key值相同(對於基礎數據類型),key值equal map中的key值(String或者封裝類型,引用類型))那麼將覆蓋其原有的value。
因此,緣由找到了,是由於people1和people2的hashcode不相同,致使沒有覆蓋。
在key,也就是value類中添加對hashcode的重寫。
public int hashCode() { int result = 17; result = 37 * result + name.hashCode(); result = 37 * result + id; return result; }
或者簡單的能夠這樣寫:
public int hashCode(){ return 50; }
添加完對hashcode的重寫以後,運行結果:
因此,通常對equals進行重寫的時候,也要把hashcode重寫!
2.hashMap跟hashTable的區別?
答:
HashTable和HashMap區別
①繼承不一樣。
public class Hashtable extends Dictionary implements Map public class HashMap extends AbstractMap implements Map
②
Hashtable 中的方法是同步的,而HashMap中的方法在缺省狀況下是非同步的。在多線程併發的環境下,能夠直接使用Hashtable,可是要使用HashMap的話就要本身增長同步處理了。
③
Hashtable中,key和value都不容許出現null值。
在HashMap中,null能夠做爲鍵,這樣的鍵只有一個;能夠有一個或多個鍵所對應的值爲null。當get()方法返回null值時,便可以表示 HashMap中沒有該鍵,也能夠表示該鍵所對應的值爲null。所以,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。
④兩個遍歷方式的內部實現上不一樣。
Hashtable、HashMap都使用了 Iterator。而因爲歷史緣由,Hashtable還使用了Enumeration的方式 。
⑤
哈希值的使用不一樣,HashTable直接使用對象的hashCode。而HashMap從新計算hash值。
⑥
Hashtable和HashMap它們兩個內部實現方式的數組的初始大小和擴容的方式。HashTable中hash數組默認大小是11,增長的方式是 old*2+1。HashMap中hash數組的默認大小是16,並且必定是2的指數。