Java集合源碼分析(五)HashSet<E>,javahashset

來源:互聯網
上載者:User

Java集合源碼分析(五)HashSet<E>,javahashset
HashSet簡介

  HashSet實現Set介面,由雜湊表(實際上是一個HashMap執行個體)支援。它不保證set 的迭代順序;特別是它不保證該順序恒久不變。此類允許使用null元素。

HashSet源碼分析

  對於HashSet而言,它是基於HashMap實現的,HashSet底層使用HashMap來儲存所有元素,因此HashSet 的實現比較簡單,相關HashSet的操作,基本上都是直接調用底層HashMap的相關方法來完成,
  HashSet的原始碼如下:

/* * @(#)HashSet.java1.37 06/04/21 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;/** * @param <E> the type of elements maintained by this set * * @author  Josh Bloch * @author  Neal Gafter * @version 1.37, 04/21/06 * @see    Collection * @see    Set * @see    TreeSet * @see    HashMap * @since   1.2 */public class HashSet<E>    extends AbstractSet<E>    implements Set<E>, Cloneable, java.io.Serializable{    static final long serialVersionUID = -5024744406713321676L;// 使用HashMap來儲存HashSet中所有元素。    private transient HashMap<E,Object> map;    // 定義一個虛擬Object對象作為HashMap的value,將此對象定義為static final。    private static final Object PRESENT = new Object();    // 預設的無參構造器,構造一個空的HashSet。實際底層會初始化一個空的HashMap。    public HashSet() {map = new HashMap<E,Object>();    }    // 構造一個包含指定collection中的元素的新set。    // 實際底層使用傳入Collection除以0.75再加1大小的HashMap或者大小為16的HashMap,這兩個值之間取最大    public HashSet(Collection<? extends E> c) {map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));addAll(c);    }    /**     * 以指定的initialCapacity和loadFactor構造一個空的HashSet。     * 實際底層以相應的參數構造一個空的HashMap。     *      * @param initialCapacity     * 初始容量     * @param loadFactor     * 載入因子     */    public HashSet(int initialCapacity, float loadFactor) {map = new HashMap<E,Object>(initialCapacity, loadFactor);    }    /**     * 以指定的initialCapacity構造一個空的HashSet。     * 實際底層以相應的參數構造一個空的HashMap。     * @param initialCapacity     * 初始容量     */    public HashSet(int initialCapacity) {map = new HashMap<E,Object>(initialCapacity);    }    /**     * 以指定的initialCapacity和loadFactor構造一個新的空連結雜湊集合。     * 此建構函式為包存取權限,不對外公開,實際只是是對LinkedHashSet的支援。     *      * 實際底層會以指定的參數構造一個空LinkedHashMap執行個體來實現。     * @param initialCapacity     * 初始容量     * @param loadFactor     * 載入因子     * @param dummy     * 標記     */    HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);    }    /**     * 返回對此set中元素進行迭代的迭代器。返回元素的順序並不是特定的。     *      * 底層實際調用底層HashMap的keySet來返回所有的key。     * 可見HashSet中的元素,只是存放在了底層HashMap的key上,     * value使用一個static final的Object對象標識。     * @return 對此set中元素進行迭代的Iterator。     */    public Iterator<E> iterator() {return map.keySet().iterator();    }    // 返回此set中的元素的數量(set的容量)。    // 底層實際調用HashMap的size()方法返回Entry的數量,就得到該Set中元素的個數。    public int size() {return map.size();    }    // 如果此set不包含任何元素,則返回true。    // 底層實際調用HashMap的isEmpty()判斷該HashSet是否為空白。    public boolean isEmpty() {return map.isEmpty();    }    // 如果此set包含指定元素,則返回true。    // 更確切地講,若且唯若此set包含一個滿足(o==null ? e==null : o.equals(e))的e元素時,返回true。    public boolean contains(Object o) {return map.containsKey(o);    }    // 如果此set中尚未包含指定元素,則添加指定元素。    // 更確切地講,如果此 set 沒有包含滿足(e==null ? e2==null : e.equals(e2))的元素e2,則向此set 添加指定的元素e。    // 如果此set已包含該元素,則該調用不更改set並返回false。    // 底層實際將將該元素作為key放入HashMap。    // 由於HashMap的put()方法添加key-value對時,當新放入HashMap的Entry中key與集合中原有Entry的key相同(hashCode()傳回值相等,通過equals比較也返回true),    // 新添加的Entry的value會將覆蓋原來Entry的value,但key不會有任何改變,    // 因此如果向HashSet中添加一個已經存在的元素時,新添加的集合元素將不會被放入HashMap中,原來的元素也不會有任何改變,這也就滿足了Set中元素不重複的特性。    public boolean add(E e) {return map.put(e, PRESENT)==null;    }    // 如果指定元素存在於此set中,則將其移除。    // 更確切地講,如果此set包含一個滿足(o==null ? e==null : o.equals(e))的元素e,    // 則將其移除。如果此set已包含該元素,則返回true     // (或者:如果此set因調用而發生更改,則返回true)。(一旦調用返回,則此set不再包含該元素)。    public boolean remove(Object o) {return map.remove(o)==PRESENT;    }    // 從此set中移除所有元素。此調用返回後,該set將為空白。    public void clear() {map.clear();    }    // 返回此HashSet執行個體的淺表副本:並沒有複製這些元素本身。    // 底層實際調用HashMap的clone()方法,擷取HashMap的淺表副本,並設定到  HashSet中。    public Object clone() {try {    HashSet<E> newSet = (HashSet<E>) super.clone();    newSet.map = (HashMap<E, Object>) map.clone();    return newSet;} catch (CloneNotSupportedException e) {    throw new InternalError();}    }    // java.io.Serializable的寫入函數    private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException {// Write out any hidden serialization magics.defaultWriteObject();        // Write out HashMap capacity and load factor        s.writeInt(map.capacity());        s.writeFloat(map.loadFactor());        // Write out size        s.writeInt(map.size());// Write out all elements in the proper order.for (Iterator i=map.keySet().iterator(); i.hasNext(); )            s.writeObject(i.next());    }    // java.io.Serializable的讀取函數    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {// Read in any hidden serialization magics.defaultReadObject();        // Read in HashMap capacity and load factor and create backing HashMap        int capacity = s.readInt();        float loadFactor = s.readFloat();        map = (((HashSet)this) instanceof LinkedHashSet ?               new LinkedHashMap<E,Object>(capacity, loadFactor) :               new HashMap<E,Object>(capacity, loadFactor));        // Read in size        int size = s.readInt();// Read in all elements in the proper order.for (int i=0; i<size; i++) {            E e = (E) s.readObject();            map.put(e, PRESENT);        }    }}

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.