java源码分析之HashMap(五)

2014-11-24 11:24:54 · 作者: · 浏览: 42
lue;
5 }
6 return null;
7 }
这是一个私有方法,只在get中被调用。该方法判断table[0]中的链表是否包含key为null的元素,包含则返回value,不包含则返回null。为什么是遍历table[0]的链表?因为key为null的时候获得的hash值都是0。
添加(put)和获取(get)都结束了,接着看如何判断一个元素是否存在。
HashMap没有提供判断元素是否存在的方法,只提供了判断Key是否存在及Value是否存在的方法,分别是containsKey(Object key)、containsValue(Object value)。
containsKey(Object key)方法很简单,只是判断getEntry(key)的结果是否为null,是则返回false,否返回true。
1 public boolean containsKey(Object key) {
2 return getEntry(key) != null;
3 }
4 final Entry getEntry(Object key) {
5 int hash = (key == null) 0 : hash(key.hashCode());
6 for (Entry e = table[indexFor(hash, table.length)];
7 e != null;
8 e = e.next) {
9 Object k;
10 if (e.hash == hash &&
11 ((k = e.key) == key || (key != null && key.equals(k))))
12 return e;
13 }
14 return null;
15 }
getEntry(Object key)也没什么内容,只是根据key对应的hash值计算在table数组中的索引位置,然后遍历该链表判断是否存在相同的key值。
1 public boolean containsValue(Object value) {
2 if (value == null)
3 return containsNullValue();
4
5 Entry[] tab = table;
6 for (int i = 0; i < tab.length ; i++)
7 for (Entry e = tab[i] ; e != null ; e = e.next)
8 if (value.equals(e.value))
9 return true;
10 return false;
11 }
12 private boolean containsNullValue() {
13 Entry[] tab = table;
14 for (int i = 0; i < tab.length ; i++)
15 for (Entry e = tab[i] ; e != null ; e = e.next)
16 if (e.value == null)
17 return true;
18 return false;
19 }
判断一个value是否存在比判断key是否存在还要简单,就是遍历所有元素判断是否有相等的值。这里分为两种情况处理,value为null何不为null的情况,但内容差不多,只是判断相等的方式不同。
这个判断是否存在必须遍历所有元素,是一个双重循环的过程,因此是比较耗时的操作。
接着看HashMap中“删除”相关的操作,有remove(Object key)和clear()两个方法。
remove(Object key)
1 public V remove(Object key) {
2 Entry e = removeEntryForKey(key);
3 return (e == null null : e.value);
4 }
看这个方法,removeEntryKey(key)的返回结果应该是被移除的元素,如果不存在这个元素则返回为null。remove方法根据removeEntryKey返回的结果e是否为null返回null或e.value。
removeEntryForKey(Object key)
1 final Entry removeEntryForKey(Object key) {
2 int hash = (key == null) 0 : hash(key.hashCode());
3 int i = indexFor(hash, table.length);
4 Entry prev = table[i];
5 Entry e = prev;
6
7 while (e != null) {
8 Entry next = e.next;
9 Object k;
10 if (e.hash == hash &&
11 ((k = e.key) == key || (key != null && key.equals(k)))) {
12 modCount++;
13 size--;
14 if (prev == e)
15 table[i] = next;
16 else
17 prev.next = next;
18 e.recordRemoval(this);
19 return e;
20 }
21 prev = e;
22 e = next;
23 }
24
25 return e;
26 }
上面的这个过程就是先找到table数组中对应的索引,接着就类似于一般的链表的删除操作,而且是单向链表删除节点,很简单。在C语言中就是修改指针,这个例子中就是将要删除节点的前一节点的next指向删除被删除节点的next即可。
clear()
1 public void clear() {
2 modCount++;
3 Entry[] tab = table;
4 for (int i = 0; i < tab.length; i++)
5 tab[i] = null;
6 size = 0;
7 }
clear()方法删除HashMap中所有的元素,这里就不用一个个删除节点了,而是直接将table数组内容都置空,这样所有的链表都已经无法访问,Java的垃圾回收机制会去处理这些链表。table数组置空后修改size为0。