HashSet深入

map.put("key1","一树梨花压海棠");// return null;
map.put("key1","两只老虎跑得快");// return "一树梨花压海棠";
/**hashmap 源码截取**/
 public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    /**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node[] tab; Node p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

其它的咱也看不懂,看看关键部位就好了。
可以看到,不存在该key的时候会直接返回null值;
存在该key时,则返回被覆盖掉的value值。

下面是hashset

hashset底层使用hashmap,可以联想到:hashset为无序不可重复,hashmap也是的keys也是不可重复的,所以在设计hashset的时候利用了这点(也可能是他们偷懒呢)来保证的。

/**hashset源码截取**/
public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

要知道,

Set s = new HashSet();
s.add("QAQ");//return true;
s.add("QAQ");//return false;

添加成功返回true,即底层的map的keys中原先是不存在"QAQ"的,依照前面所讲,map.put("QAQ",PRESENT)肯定是返回null值(PRESENT是一个虚拟值↓↓↓↓↓↓↓↓)。

/**hashset源码截取**/
// Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

我们还需要注意到的细节是,要保证HashSet存入对象的唯一性,需要对存入的对象类进行hashcode和equals方法的重写。这一点在map的keys中亦如此。

你可能感兴趣的:(HashSet深入)