赞
踩
HashMap可以用键值对来存储对象,所谓键值对,就是可以通过对象来寻找对象,是对数组索引的推广。
HashMap底层的实现采用了哈希表,基本结构是“数组+链表”。HashMap里面有一个叫table的Entry数组,Entry是一个用作链表节点的类,也就是说,数组的每个元素都对应着一个链表,结构如图所示:
当调用HashMap的put方法时
注:两种最极端的计算哈希值算法:1.hashCode / hashCode 退化成一个链表 2.hashCode / 1退化成一个数组
注:为了提高效率,会将模运算换成位运算,当length是2的幂次时,hashCode & (length - 1)等效于hashCode % length
注:JDK8中,当链表长度大于8时,会将链表转化成一颗红黑树,提高查找效率
查找的过程类似于存储过程,只不过把存改为找到后返回。
当数组使用了四分之三的长度时,会进行扩容,扩容为原来长度的两倍,实质上是新定义一个两倍长度的数组,再进行数组拷贝。
只是对HashMap的简单实现,许多情况并未考虑,仅仅是为了方便理解HashMap的两个核心方法:get()和put();
/**
* 用于HashMap
* TODO
* @version 1.0
* @author 王星宇
*/
class node<K,V>{
int hash;
K key;
V value;
node next;
}
node[] table; //位桶数组 buckey array
int size;
/**
* 构造方法 ,默认16(2的整数次幂)个
*/
myHashMap(){
table = new node[16] ; // 2 的整数次幂
}
/**
* 计算v的哈希值
* @param key key的hashCode
* @param length 数组长度
* @return v的哈希值
*/
public int myHash(int key,int length) {
return key & (length - 1);
}
/** * 重写toString方法 */ @Override public String toString() { StringBuffer SB = new StringBuffer("["); for(int i = 0;i < table.length;i++) { node temp = table[i]; while(temp != null) { SB.append(temp.key + "=" + temp.value + ","); temp = temp.next; } } SB.setCharAt(SB.length() - 1, ']'); return SB.toString(); }
/** * 存放键值对,未考虑数组扩容 * @param key * @param value */ public void put(K key,V value) { node newNode = new node(); newNode.hash = myHash(key.hashCode(),table.length); newNode.key = key; newNode.value = value; newNode.next = null; node temp = table[newNode.hash]; node last = null;//链表最后一个节点 if(temp == null) { table[newNode.hash] = newNode; size++; }else { while(temp != null) { if(temp.key.equals(key)) { temp.value = value; break; }else { last = temp; temp = temp.next; } } if(temp == null) { last.next = newNode; size++; } } }
public V get(K key) { int hash = myHash(key.hashCode(),table.length); V value = null; if(table[hash] != null) { node temp = table[hash]; while(temp != null) { if(temp.key.equals(key)){ value = (V)temp.value; break; } temp = temp.next; } } return value; }
package myCollection; /** * 测试HashMap * TODO * @version 1.0 * @author 王星宇 */ public class myHashMap <K,V>{ node[] table; //位桶数组 buckey array int size; /** * 构造方法 ,默认16(2的整数次幂)个 */ myHashMap(){ table = new node[16] ; // 2 的整数次幂 } /** * 存放键值对,未考虑数组扩容 * @param key * @param value */ public void put(K key,V value) { node newNode = new node(); newNode.hash = myHash(key.hashCode(),table.length); newNode.key = key; newNode.value = value; newNode.next = null; node temp = table[newNode.hash]; node last = null;//链表最后一个节点 if(temp == null) { table[newNode.hash] = newNode; size++; }else { while(temp != null) { if(temp.key.equals(key)) { temp.value = value; break; }else { last = temp; temp = temp.next; } } if(temp == null) { last.next = newNode; size++; } } } /** * 计算v的哈希值 * @param key key的hashCode * @param length 数组长度 * @return v的哈希值 */ public int myHash(int key,int length) { return key & (length - 1); } /** * 重写toString方法 */ @Override public String toString() { StringBuffer SB = new StringBuffer("["); for(int i = 0;i < table.length;i++) { node temp = table[i]; while(temp != null) { SB.append(temp.key + "=" + temp.value + ","); temp = temp.next; } } SB.setCharAt(SB.length() - 1, ']'); return SB.toString(); } public V get(K key) { int hash = myHash(key.hashCode(),table.length); V value = null; if(table[hash] != null) { node temp = table[hash]; while(temp != null) { if(temp.key.equals(key)){ value = (V)temp.value; break; } temp = temp.next; } } return value; } } /** * 用于HashMap * TODO * @version 1.0 * @author 王星宇 */ class node<K,V>{ int hash; K key; V value; node next; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。