我们先看2个类的定义
```
public class Hashtable
extends Dictionary
implements Map, Cloneable, java.io.Serializable
```
```
public class HashMap
extends AbstractMap
implements Map, Cloneable, Serializable
```
可见Hashtable 继承自 Dictiionary 而 HashMap继承自AbstractMap
Hashtable的put方法如下
```
public synchronized V put(K key, V value) { //###### 注意这里1
// Make sure the value is not null
if (value == null) { //###### 注意这里 2
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry tab[] = table;
int hash = key.hashCode(); //###### 注意这里 3
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index]; e != null; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V old = e.value;
e.value = value;
return old;
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
Entry e = tab[index];
tab[index] = new Entry(hash, key, value, e);
count++;
return null;
}
```
注意1 方法是同步的
注意2 方法不允许value==null
注意3 方法调用了key的hashCode方法,如果key==null,会抛出空指针异常
HashMap的put方法如下
```
public V put(K key, V value) { //###### 注意这里 1
if (key == null) //###### 注意这里 2
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry 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;
}
```
注意1 方法是非同步的
注意2 方法允许key==null
注意3 方法并没有对value进行任何调用,所以允许为null
补充:
Hashtable 有一个 contains方法,容易引起误会,所以在HashMap里面已经去掉了
当然,2个类都用containsKey和containsValue方法。
结论: HashMap 在大多数情况下是优先选择的。
HashMap可以通过下面的语句进行同步:
`Map m = Collections.synchronizeMap(hashMap);`
来自:
http://blog.csdn.net/java2000_net/article/details/2512510
2. HashTable和HashMap区别
第一,继承不同。
public class Hashtable extends Dictionary implements Map
public class HashMap extends AbstractMap implements Map
第二
Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
第三
Hashtable中,key和value都不允许出现null值。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
第四,两个遍历方式的内部实现上不同。
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
第五
哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
Hashtable: Object->hashCode()
```
//1.6HashMap
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
```
1.7以上HashMap:Objects.hashCode(key) ^ Objects.hashCode(value)
第六
Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
来自:
http://www.cnblogs.com/devinzhang/archive/2012/01/13/2321481.html
- 参考资料
- 容器的实现
- ArrayList、LinkedList与Vector的区别
- Map,Set,List,Queue,Stack的特点与用法
- HashMap的实现
- HashMap和ConcurrentHashMap差别
- HashMap和HashTable的区别
- fast fail
- java 实用方法
- Collections中实用的函数
- ArrayList中实用的函数
- Integer和Character
- Properties类的简单使用
- XML实用解析
- 从jar包中读取文件信息
- java自带base64加密解密
- java机制
- 分派
- 反射
- 类加载机制
- java中一个对象的初始化
- 泛型
- 自动装箱,拆箱与遍历循环
- 偏向于语法
- new int[]
- new boolean[]
- Switch能否用string做参数
- equals与==的区别
- 泛型对象数组
- Enum的用法
- String、StringBuffer与StringBuilder的区别
- try catch finally
- finalize方法
- object有哪些公用方法
- Java的四种引用,强弱软虚,用到的场景
- java访问修饰符
- Hashcode的作用
- 九种基本数据类型
- java对象大小
- 数组长度
- 动态代理的一个例子
- java.lang.NoClassDefFoundError
- ThreadLocal