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

 

posted on 2018-10-14 12:16  溪水静幽  阅读(343)  评论(0)    收藏  举报