HashMap和HashSet的底层实现
来源:互联网 发布:网络加速器国外节点 编辑:程序博客网 时间:2024/06/04 20:03
HashMap和HashSet是Map接口、Set接口常用的实现类,因此研究这两个实现原理有助于更好的使用它们,并理解他们的区别。
下面先来分析HashMap的底层实现。
Map中存储的是<Key,value>对,每个<Key,value>对都以Map.Entry的数据结构存储,然后用一个table数组来存储Entry,该table就是根据实例化的参数创建的数组。
存储的位置则按照Key计算的hash返回值来计算。
以下是Java源代码HashMap类中添加元素的函数。
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable, initHashSeedAsNeeded(newCapacity));
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
由此可以看出,当数组的元素已满时,则double其容量。
然后在bucketindex位置创建一个新的Entry,如果此处已经有一个Entry,则新的Entry指向原来的Entry,产生一个Entry链,并且新放入的Entry永远处于Entry链的起端,位于数组bucket中。
当查询元素时,调用get()函数。
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
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 != null && key.equals(k))))
return e;
}
return null;
}
可见新根据key计算的hash值去找相应的bucket,如果该bucket只有一个元素则直接返回该Value,如果存在一个Entry链的话,必须遍历整个Entry链才能找到相应的value值。
由此可见,当table中的每个bucket中都只有一个Entry元素时,该hashMap的性能最好。
明白了HashMap的原理,HashSet就迎刃而解了。因为HashSet的底层就是用HasHMap来实现的,即把HashMap中的key来存储元素即实现了set.
我们来看一下HashSet的源码便知。
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
- HashMap和HashSet的底层实现
- HashMap和HashSet原理及底层实现
- HashSet 与HashMap底层实现
- HashSet 与HashMap底层实现
- HashSet与HashMap底层实现
- HashSet和HashMap的底层实现——哈希表、散列表
- HashSet和HashMap的底层实现——哈希表、散列表
- HashSet的底层实现了解和使用方法
- hashset的底层实现
- TreeSet、TreeMap、HashSet、HashMap底层实现
- 实现自己的hashset和hashmap
- java中HashMap和HashSet的实现
- Java之HashMap底层实现原理/HashMap、HashTable、HashSet
- JAVA数据结构和算法:第四章(HashMap和HashSet底层原理及实现)
- HashMap的实现原理和底层数据结构
- HashMap的实现原理和底层数据结构
- HashMap的实现原理和底层数据结构
- HashMap的实现原理和底层数据结构
- 用Discuz 搭建个人论坛
- 添加超链接
- Watch OS 2 Complication 开发教程 (二) (持续连载中)
- 机器学习理论依据
- linux常用命令
- HashMap和HashSet的底层实现
- POJ 1961 Period kmp
- Spring入门
- 递归
- 华为OJ平台试题 —— 字符串:图片整理
- {System.InvalidOperationException: 无效操作。连接被关闭。
- [LeetCode164] Maximum Gap
- Poj 2826 An Easy Problem!
- 关于self点操作访问和下划线访问的区别