我是靠谱客的博主 害怕奇迹,最近开发中收集的这篇文章主要介绍java.util.HashMap源码初探,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

对于一个存储类的分析,无非从两点入手:存储用的数据结构,存储的运行机制。

数据结构:

数组


/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient Entry[] table;

Entry

链表格式。

也即,HashMap中采用的是“链接法”来处理碰撞问题的。


运行机制:

put、get

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;
}

get方法


public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}

可以看出,重要的一句代码为:

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))


这句代码的作用是判断两个Key对象是否“相同”,这里的相同的意思是指两个Key完全可以不分彼此,可以作为同一个Key使用。

在put方法中,如果两个Key的hashCode相同,且equals符合,这里是把原有的的value替换成新的value。


测试代码:

package test.junit;
import java.util.HashMap;
import junit.framework.TestCase;
/**
* HashMap中判断两个Key是否相同:先判断hashCode,在判断是否equals
* e.hash == hash && ((k = e.key) == key || key.equals(k))
* @author xuefeng
*
*/
public class HashMapTest extends TestCase {
/**
* v1和v4的hashCode相同,但是equals不符合,所以v1和v4会组成一个链表。
*/
public void testKey1() {
HashMap<Key, Value> map = new HashMap<Key, Value>();
Key k1 = new Key(1);
Key k4 = new Key(4);
Value v1 = new Value(1);
Value v4 = new Value(4);
map.put(k1, v1);
map.put(k4, v4);
assertEquals(v1, map.get(k1));
assertEquals(v4, map.get(k4));
}
/**
* v1和v4的hashCode相同,而且equals也符合,所以v1会被v4替换掉,k1和k4指向同一个v4。
*/
public void testKey2() {
HashMap<Key2, Value> map = new HashMap<Key2, Value>();
Key2 k1 = new Key2(1);
Key2 k4 = new Key2(4);
Value v1 = new Value(1);
Value v4 = new Value(4);
map.put(k1, v1);
map.put(k4, v4); // 这里会替换掉v1
//
assertEquals(v1, map.get(k1));
assertEquals(v4, map.get(k1));
assertEquals(v4, map.get(k4));
}
}
class Key {
public int m;
public Key(int m) {
this.m = m;
}
@Override
public int hashCode() {
return m%3;
}
}
class Value {
public int m;
public Value(int m) {
this.m = m;
}
}
class Key2 {
public int m;
public Key2(int m) {
this.m = m;
}
@Override
public int hashCode() {
return m%3;
}
@Override
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof Key2)) return false;
Key2 other = (Key2)obj;
return this.hashCode() == other.hashCode();
}
}


最后

以上就是害怕奇迹为你收集整理的java.util.HashMap源码初探的全部内容,希望文章能够帮你解决java.util.HashMap源码初探所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部