1. java.util.HashMap的底層實現是數組+鏈表。
2. 簡介put(key, value)方法的執行過程:
1)通過key值,使用散列算法計算出來一個hash值,用來確定該元素需要存儲到數組中的哪個位置(index)。
2)根據計算出來的位置(index),可以查看該位置是否被占用:
2.1)如果位置(index)未被占用,將(key\value)封裝成一個節點,保存到該位置。
2.2)如果位置(index)被占用,使用key和鏈表中的節點一一比較:
---->如果鏈表中不存在該key,將(key/value)封裝成節點添加到該鏈表中。
---->如果鏈表中已存在該key,替換該key對應節點的value值。
3. 簡介get(key)方法的執行過程:
1)通過key的hash值可以計算出當前元素所在鏈表存儲在數組中的位置(index)。
2)通過key值和鏈表中的節點一一比較,可以得到key值對應的元素。
4. 可以看出:
1)key的hashCode方法很重要。因為要根據hashCode的值計算該元素要存在數組中的那個位置(index)。
2)key的equals方法很重要。因為要根據equals方法來比較,數組某個位置的鏈表中是否已包含該元素(節點)。
所以:
key/value一旦存入到map當中,不能再去改變key的值。
一旦改變了key的值(比如說改變key中某個用來生成hashCode的屬性),就不能根據這個key來找到元素存在數組中的位置了。
5. 一般做法:
1)需要重寫key對象類的hashCode方法。最好用可以唯一標識該對象的屬性來生成hashCode。
2)需要重寫key對象的equals方法。可以用唯一標識的一個或多個屬性來重寫equals方法。如果不重寫equals方法,對象比較時,會比較在內存中的地址。
一小段代碼:
import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.junit.Before; import org.junit.Test; public class TestMap { Map<User, Integer> map; User user1; User user2; User user3; @Before public void before() { map = new HashMap<User, Integer>(); user1 = new User("320381", "zhangSan", 20); user2 = new User("320382", "LiSi", 22); user3 = new User("320383", "Wangwu", 25); map.put(user1, 1); map.put(user2, 2); map.put(user3, 3); } // 先看看map里都有什么 @Test public void test1() { System.out.println(map); // {320383-Wangwu=3, 320381-zhangSan=1, 320382-LiSi=2} } // 改變了key值,再執行刪除操作,刪不掉了 @Test public void test2() { user1.setIdCardNo("320384"); map.remove(user1); System.out.println(map); // {320383-Wangwu=3, 320384-zhangSan=1, 320382-LiSi=2} } // 遍歷map-方法1 @Test public void test3() { for (User user : map.keySet()) { System.out.println(user); System.out.println(map.get(user)); } } // 遍歷map-方法2 @Test public void test4() { for (Entry<User, Integer> en : map.entrySet()) { System.out.println(en.getKey()); System.out.println(en.getValue()); } } } class User { private String IdCardNo; private String name; private int age; public User() { super(); } public User(String idCardNo, String name, int age) { super(); IdCardNo = idCardNo; this.name = name; this.age = age; } // 重寫了hashCode方法 public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((IdCardNo == null) ? 0 : IdCardNo.hashCode()); return result; } // 重寫了equals方法 public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (IdCardNo == null) { if (other.IdCardNo != null) return false; } else if (!IdCardNo.equals(other.IdCardNo)) return false; return true; } // 重寫了toString方法 public String toString() { return IdCardNo + "-" + name; }
// getters/setters(略) }