HashMap的底层实现主要是基于数组和链表来实现的,HashMap中通过key的hashCode来计算hash值的,由这个hash值计算在数组中的位置,将新插入的元素放到数组的这个位置,如果新插入的元素的hash值跟这个位置上已有元素的hash值相同,就会出现hash冲突,这时候,就在该位置通过链表来插入新的元素。
这里懒的画图了,借鉴http://www.cnblogs.com/chengxiao/p/6059914.html的图说明一下HashMap的底层数组加链表的结构。
我在图中标注了红色的框表示数组的结构,只有出现hash冲突的时候(横排数组位置已经有元素占了),才会在该位置通过链表的形式插入新元素,也是紫色的方框。
Map接口类:
package com.java.myutil;
public interface Map {
int size();
boolean isEmpty();
Object get(Object key);
Object put(Object key, Object value);
interface Entry{
Object getKey();
Object getValue();
}
}
HashMap的实现:
package com.java.myutil;
/**
* 数组加链表的结构
*/
public class HashMap implements Map {
//默认容量16
private final int DEFALUT_CAPACITY=16;
//内部存储结构,数组
Node[] table=new Node[DEFALUT_CAPACITY];
private int size=0;
public int size() {
return size;
}
public boolean isEmpty() {
return size==0;
}
public Object get(Object key) {
int hashValue=hash(key);
int i=indexFor(hashValue, table.length);
for (Node node = table[i]; node!=null; node=node.next) {
if (node.key.equals(key)&&hashValue==node.hash) {
return node.value;
}
}
return null;
}
public Object put(Object key,Object value) {
//通过key,求hash值
int hashValue=hash(key);
//同过hash值,找到这个key应该放在数组的哪个位置(i)
int i=indexFor(hashValue,table.length);
//i位置已经有数据了
for (Node node = table[i]; node!=null; node=node.next) {
Object k;
//且数组中已有这个key的,覆盖其原始的value
if (node.hash==hashValue&&((k=node.key)==key||key.equals(k))) {
Object oldValue=node.value;
node.value=value;
return oldValue;
}
}
//如果i位置没有数据,或者i位置有数据,但是key是新的key,则新增节点
addEntry(key, value, hashValue, i);
return null;
}
public void addEntry(Object key, Object value, int hashValue, int i) {
//如果超过了数组原始的大小,则扩大数组
if (++size==table.length) {
Node [] newTable=new Node[table.length*2];
System.arraycopy(table, 0, newTable, 0, table.length);
table=newTable;
}
//得到i位置的数据
Node eNode=table[i];
//新增节点,将该节点的next值指向前一个节点
table[i]=new Node(hashValue, key, value, eNode);
/*
* 上面两句话,需要注意的是,如果i位置原始位置table[i]没有值,
* eNode为空,就直接将新的node放入table[i],并将该node的next指向空
新的node插入到原始node的前面,所以新的node的next指向原始位置i的node
*/
}
public int indexFor(int hashValue, int length) {
return hashValue%length;
}
public int hash(Object key) {
return key.hashCode();
}
static class Node implements Map.Entry{
int hash;
Object key;
Object value;
Node next;//指向下一个节点
Node(int hash, Object key, Object value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public Object getKey() {
return key;
}
public Object getValue() {
return value;
}
}
public static void main(String[] args) {
HashMap hashMap=new HashMap();
hashMap.put("aaa", "1111");
hashMap.put("bbb", "2222");
hashMap.put("ccc", "3333");
hashMap.put("ddd", "4444");
hashMap.put("eee", "5555");
hashMap.put("ffff", "9666");
hashMap.put("ggg", "geg");
System.out.println(hashMap.get("ggg"));
}
}