java——HashSet中add()方法不能加重復值得原因理解(我們一起來看底層代碼吧)


Set<String> names = new HashSet<>();
        names.add("張三");
        names.add(new String("張三"));
        
        Iterator<String> iterator = names.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }

以上代碼輸出只有一個:張三

驚不驚喜,意不意外???

 

下面我們來看原因

按住ctrl鍵點擊add進入到public interface Set<E> extends Collection<E> Set接口中的add抽象方法

 

boolean add(E e);

 

然后按住ctrl鍵盤點擊到HashSet類中重新的add方法

 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

按住ctrl鍵點擊put  進入到HashMap類中的put方法

  public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

其中的hash(key)是HashMap中的方法

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

返回的值是key.hashCode()的相關轉換,我們就看key.hashCode()的值是什么了  那我們來看一下這個方法

    public native int hashCode();//是Object類中的一個抽象方法

其中有繼承重寫這個方法的,但是打開Eclipse就會bug 試了兩次了  ,那我們就不打開了

但是我們可以得到一個結論

本身HashSet中的hashCode()方法就是同一個對象的hashCode()的返回值是相等的

我們可以自己重寫hashCode()方法來判斷他返回的值

並且其中putVal()方法也在HashMap方法中final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {

 Node<K,V>[] tab; Node<K,V> 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<K,V> e; K k;
      /*
      怎么判斷相等的就是用下面的紅色代碼
        p.hash==hash 就是調用hash(key)方法后的值,只要是同一個對象,返回值就相同(可以重寫hashCode()方法)
    
        (k = p.key) == key判斷兩個對象的地址是否相同
        
          key.equals(k)默認調用Object類中的equals方法判斷地址是否相同,可以重寫equals方法
        如果以上滿足
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
          那么這兩個值就是相同的,后來的就會覆蓋前面的。

       */
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)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; }

分析:為上面青色字體

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM