不同点:
1. HashMap允许空(null)键值(key),Hashtable不行
HashMap map = new HashMap(); //HashMap
map.put("a", null);
map.put(null, "b");
map.put(null, null); //编译运行,都可以
Hashtable table = new Hashtable(); //HashTable
table.put("a", null); //编译正常,运行时空指针异常,键或值都不能为空
table.put(null, "123"); //同上
2. HashMap把Hashtable的contains方法去掉了。也有 containsvalue和containsKey方法
map.containsValue(""); //查询是否有值为""的数据
map.containsKey(""); //查询键
table.contains(""); //查询值,和下面的重复,容易造成误解,所以HashMap去掉了
table.containsValue(""); //查询值
table.containsKey(""); //查询键 都返回false或true
3. 历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类
HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
Hashtable<K,V> extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable
4. 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
Map m = Collections.synchronizedMap(new HashMap()); //HashMap同步的方法,使在多线程中也安全
(这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法)
(线程同步,安全;线程不同步,不安全)
|
<!--[if !vml]-->
<!--[endif]--> |
HashMap
|
Hashtable
|
|
继承,实现
|
HashMap<K,V>
extends AbstractMap<K,V>
implementsMap<K,V>,
Cloneable, Serializable
|
Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>,
Cloneable,Serializable
|
|
多线程,同步
|
未同步的,可以使用Colletcions进行同步
Map Collections.synchronizedMap(Map m)
|
已经同步过的可以安全使用
|
|
对null的处理
|
HashMap map = new HashMap();
map.put(null, "Null");
map.put("Null", null);
map.containsKey(null);
map.containsValue(null);
以上这5条语句无论在编译期,还是在运行期都是没有错误的.
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
|
Hashtable table = new Hashtable();
table.put(null, "Null");
table.put("Null", null);
table.contains(null);
table.containsKey(null);
table.containsValue(null);
后面的5句话在编译的时候不会有异常,可在运行的时候会报空指针异常
具体原因可以查看源代码
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
………….
|
|
增长率
|
void addEntry(int hash,
K key, V value,int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex]
= newEntry<K,V>(hash, key, value, e);
if (size++
>= threshold)
resize(2 * table.length);
}
|
protectedvoid rehash()
{
int oldCapacity
=table.length;
Entry[] oldMap = table;
int newCapacity
= oldCapacity * 2 + 1;
Entry[] newMap = newEntry[newCapacity];
modCount++;
threshold =
(int)(newCapacity * loadFactor);
table =
newMap;
for (int i
= oldCapacity ; i-- > 0 ;) {
for (Entry<K,V>
old = oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;
int index
= (e.hash & 0x7FFFFFFF) % newCapacity;
e.next =
newMap[index];
newMap[index] = e;
}
}
}
|
|
哈希值的使用
|
HashMap重新计算hash值,而且用与代替求模
publicboolean containsKey(Object
key) {
Object k = maskNull(key);
int hash
= hash(k.hashCode());
int i
= indexFor(hash, table.length);
Entry e = table[i];
while (e
!= null) {
if (e.hash
== hash && eq(k, e.key))
returntrue;
e = e.next;
}
return false;
}
|
HashTable直接使用对象的hashCode,代码是这样的:
publicsynchronizedbooleancontainsKey(Object
key) {
Entry tab[] = table;
int hash
= key.hashCode();
int index
= (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V>
e = tab[index] ; e != null ; e = e.next)
{
if ((e.hash ==
hash) && e.key.equals(key)) {
return true;
}
}
return false;
}
|
本文详细对比了HashMap与Hashtable两种Java集合类的区别,包括对null的支持、线程安全性、增长率及哈希值计算等方面的不同。
1593

被折叠的 条评论
为什么被折叠?



