Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。二者都实现了Map接口。
HashMap允许是支持null键和null值的,允许一个null键和多个null值
HashTable不允许null键值,在遇到null时,会抛出NullPointerException异常。
HashMap在实现时对null做了特殊处理,将null的hashCode值定为了0,从而将其存放在哈希表的第0个bucket中。
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Hashtable
内部的方法基本都经过synchronized
修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap(采用CAS---乐观锁和Synchronized---悲观锁),只锁住当前桶
吧!);hash不同
HashMap添加元素时,是使用自定义的哈希算法,而HashTable是直接采用key的hashCode()
HashTable 计算hash,直接用key的hashCode(),再取模,取模运算效率不高
HashMap,先得到hashCode,在高位计算,最后使用优化的取模运算
这个方法非常巧妙,它通过**h & (table.length -1)来得到该对象的保存位,而HashMap底层数组的长度总是2的n次方,这是HashMap在速度上的优化。当length总是2的n次方时**,h& (length-1)运算等价于对length取模,也就是h%length,但是&比%具有更高的效率。
在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在数组table的length比较小的时候,也能保证考虑到高低Bit都参与到Hash的计算中,同时不会有太大的开销
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
// &0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。
====================HashMap============
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
i = (n - 1) & hash
Hashtable
默认的初始大小为 11,之后每次扩充,容量变为原来的 2n+1。HashMap
默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍。HashMap
会将其扩充为 2 的幂次方大小(HashMap
中的tableSizeFor()
方法保证,下面给出了源代码)。HashMap
总是使用 2 的幂作为哈希表的大小,后面会介绍到为什么是 2 的幂次方。HashMap
要比 Hashtable
效率高一点。Hashtable
基本被淘汰,不要在代码中使用它;本文发布于:2024-02-01 01:42:58,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170672297632945.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |