1. java.util.HashMap的底层实现是数组+链表。
2. 简介put(key, value)方法的执行过程:
1)通过key值,使用散列算法计算出来一个hash值,用来确定该元素需要存储到数组中的哪个位置(index)。
2)根据计算出来的位置(index),可以查看该位置是否被占用:
2.1)如果位置(index)未被占用,将(keyvalue)封装成一个节点,保存到该位置。
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(略) }