HashMap HashSet HashTable区别
(1)HashSet是set接口的一个实现类,hashMap是Map接口的一个实现类
(2)HashSet以对象作为存储元素,而HashMap以(key-value)的键值对对象作为存储元素
(3)HashSet不允许重复的元素(不允许包含重复的值),HashMap不允许重复的键,但是允许包含重复的值
eg:HashMap is a key -> value (key to value) map, e.g. {a -> 1, b -> 2, c -> 2, d -> 1}
(4)HashSet只允许包含一个null元素,HashMap允许一个null键和许多数量的null值
HashSet不能添加重复的元素, 当调用add(Object)方法时候,
首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素;
如果已存在则调用Object对象的equals方法判断是否返回true,如果为true则说明元素已经存在,如为false则插入元素。
HashSet是借助HashMap来实现的,利用HashMap中Key的唯一性,来保证HashSet中不出现重复值。具体参见代码:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public HashSet() { map = new HashMap<E,Object>(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } }
由此可见,HashSet中的元素实际上是作为HashMap中的Key存放在HashMap中的。下面是HashMap类中的put方法:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> 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; } } }
从这段代码中可以看出,HashMap中的Key是根据对象的hashCode() 和 euqals()来判断是否唯一的。
结论:为了保证HashSet中的对象不会出现重复值,在被存放元素的类中必须要重写hashCode()和equals()这两个方法。
HashMap和HashTable的相同点
HashMap和HashTable都是存储“键值对”的散列表,而且都是采用拉链法来实现的。存储的思想都是:通过table数组存储,数组的每个元素都是一个Entry,而一个Entry就是一个单项链表,Entry链表中的每个节点都保存了key-value数据。
HashMap和HashTable的不同点
线程安全:
HashMap的方法是非同步的,若要在多线程下使用HashMap,需要我们额外的进行同步处理。对HashMap处理可以使用Collections类提供的synchronizedMap静态方法,或者直接使用JDK5.0之后提供的java.util.concurrent包里的ConcurrentHashMap类。
HashTable几乎所有方法都是同步的,前面都加了synchronized关键字,它支持多线程。
Null处理不同
HashMap的key和value都可以为null。
HashTable的key和value都不可以为null。
HashTable的key和value都不能为null,否则会抛出异常,异常是NullPointerException。HashMap的key和value都可以为null,当key为null时,HashMap会将其固定的插入table[0]位置,而且table[0]的位置只会容纳一个key为null的值。
初始容量与扩充容量不同
HashMap的默认容量是16,,扩容时,每次将容量变为原来的2倍;
HashTable的默认容量是11,扩容时,每次将容量变为原来的2倍+1。
遍历类型不同
HashMap只支持Iterator遍历。
HashTable支持Iterator和Enumeration两种方式遍历,是因为实现Directory接口。
参考:
https://stackoverflow.com/questions/2773824/difference-between-hashset-and-hashmap
https://www.cnblogs.com/duanxz/p/3890038.html
https://blog.csdn.net/eson_15/article/details/51250324
浙公网安备 33010602011771号