HashMap内部存储实现及HashTable比较
2014-04-26 10:00
239 查看
一、HashMap的内部存储实现
HashMap底层实现的数据结构是哈希表。哈希表的实现一般有两种,第一种是数组(闭散列),第二种是数组+链表(开散列)。而HashMap采用的是“数组+链表”的实现,
即数组存储链表的头结点。
1、HashMap存储数据时进行put( key, value )的操作,源代码如下:
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode()); //首先进行key.hashCode()操作,获取key的哈希值
int i = indexFor(hash, table.length); //相当于:int i = hash % Entry[].length,Entry.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;
}
注意:在Entry类里面有一个next属性,指向下一个Entry。例如,第一个键值对A进来,通过计算得到其key的hash是1,则存储:Entry[1]=A。接着,第二个键值对B进来,其key的hash也等于1,那么HashMap会这样做:B.next = A, Entry[1] = B,以此类推。由此可知,数组中存储的是最后插入的元素。
2、取出数据进行get( key )操作,源代码如下:
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
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;
}
当key不为空时,先根据hash函数得到hash值,再根据indexFor()得到数组的索引值,接着遍历链表。如果有key值等于已存在的key值,则返回其value。
二、HashMap和HashTable的比较
HashTable和HashMap采用相同的存储机制,二者的实现基本一致,不同的是:
1. HashMap是非线程安全的,HashTable是线程安全的。
2. HashMap的键和值都可以为null,但是HashTable不行。
3. 由于线程安全的关系,HashMap的效率比HashTable要高。
4. HashMap没有使用HashTable的contains()函数,取而代之的是containsKey()和containsValue()。
HashMap底层实现的数据结构是哈希表。哈希表的实现一般有两种,第一种是数组(闭散列),第二种是数组+链表(开散列)。而HashMap采用的是“数组+链表”的实现,
即数组存储链表的头结点。
1、HashMap存储数据时进行put( key, value )的操作,源代码如下:
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode()); //首先进行key.hashCode()操作,获取key的哈希值
int i = indexFor(hash, table.length); //相当于:int i = hash % Entry[].length,Entry.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;
}
注意:在Entry类里面有一个next属性,指向下一个Entry。例如,第一个键值对A进来,通过计算得到其key的hash是1,则存储:Entry[1]=A。接着,第二个键值对B进来,其key的hash也等于1,那么HashMap会这样做:B.next = A, Entry[1] = B,以此类推。由此可知,数组中存储的是最后插入的元素。
2、取出数据进行get( key )操作,源代码如下:
[java] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
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;
}
当key不为空时,先根据hash函数得到hash值,再根据indexFor()得到数组的索引值,接着遍历链表。如果有key值等于已存在的key值,则返回其value。
二、HashMap和HashTable的比较
HashTable和HashMap采用相同的存储机制,二者的实现基本一致,不同的是:
1. HashMap是非线程安全的,HashTable是线程安全的。
2. HashMap的键和值都可以为null,但是HashTable不行。
3. 由于线程安全的关系,HashMap的效率比HashTable要高。
4. HashMap没有使用HashTable的contains()函数,取而代之的是containsKey()和containsValue()。
相关文章推荐
- 背包九讲
- 使用RadControls的RadMenu控件开发系统菜单
- Windows 2003 中配ASP,ASP.NET
- js drawImage 下面代码可在IE响应,在chrome和FF不行,如何修改
- MFC对话框及窗口函数调用顺序
- Java内部类的使用小结
- 敏捷软件开发Note
- 《PIN CHANGE/UNBLOCK 命令报文》
- 不同Vlan相互通信
- 交换路由实践
- 利用JQuery显示不刷新页面获得服务器传来数据的最简单示例
- 白盒测试的逻辑覆盖测试总结
- grunt使用初步
- 程光 东南大学 教授,博导
- 如何理解闭包这一概念
- Android Webview实现文件下载功能
- MongoDB中MapReduce编程模型使用实例
- Linux下查看和踢除正在登陆的其他用户
- Android闪闪发光字体效果
- 九度OJ题目1450:产生冠军