1 table与map区别
我们先看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;
- }
注意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 在大多数情况下是优先选择的,运行速度快,但在多线程环境下要进行同步。
2 HashSet
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:
由上面源程序可以看出,HashSet 的实现其实非常简单,它只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
- public class HashSet<E>
- extends AbstractSet<E>
- implements Set<E>, Cloneable, java.io.Serializable
- {
- // 使用 HashMap 的 key 保存 HashSet 中所有元素
- private transient HashMap<E,Object> map;
- // 定义一个虚拟的 Object 对象作为 HashMap 的 value
- private static final Object PRESENT = new Object();
- ...
- // 初始化 HashSet,底层会初始化一个 HashMap
- public HashSet()
- {
- map = new HashMap<E,Object>();
- }
- // 以指定的 initialCapacity、loadFactor 创建 HashSet
- // 其实就是以相应的参数创建 HashMap
- public HashSet(int initialCapacity, float loadFactor)
- {
- map = new HashMap<E,Object>(initialCapacity, loadFactor);
- }
- public HashSet(int initialCapacity)
- {
- map = new HashMap<E,Object>(initialCapacity);
- }
- HashSet(int initialCapacity, float loadFactor, boolean dummy)
- {
- map = new LinkedHashMap<E,Object>(initialCapacity
- , loadFactor);
- }
- // 调用 map 的 keySet 来返回所有的 key
- public Iterator<E> iterator()
- {
- return map.keySet().iterator();
- }
- // 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数
- public int size()
- {
- return map.size();
- }
- // 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空,
- // 当 HashMap 为空时,对应的 HashSet 也为空
- public boolean isEmpty()
- {
- return map.isEmpty();
- }
- // 调用 HashMap 的 containsKey 判断是否包含指定 key
- //HashSet 的所有元素就是通过 HashMap 的 key 来保存的
- public boolean contains(Object o)
- {
- return map.containsKey(o);
- }
- // 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap
- public boolean add(E e)
- {
- return map.put(e, PRESENT) == null;
- }
- // 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素
- public boolean remove(Object o)
- {
- return map.remove(o)==PRESENT;
- }
- // 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
- public void clear()
- {
- map.clear();
- }
- ...
- }
由上面源程序可以看出,HashSet 的实现其实非常简单,它只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
转自:http://blog.csdn.net/java2000_net/article/details/2512510
http://alex09.iteye.com/blog/539549