Java中HashSet的解讀

字號:


    一. HashSet源代碼
    HashSet 的實現
    對于 HashSet 而言,它是基于 HashMap 實現的,HashSet 底層采用 HashMap 來保存所有元素,因此 HashSet 的實現比較簡單,查看 HashSet 的源代碼,可以看到如下代碼: Java代碼
    public class HashSet<E> extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {
    // 使用 HashMap 的 key 保存 HashSet 中所有元素 private transient HashMap<E,Object> map;
    // 定義一個虛擬的 Object 對象作為 HashMap 的 value private static final Object PRESENT = new Object(); ...
    // 初始化 HashSet,底層會初始化一個 HashMap public HashSet() {
    map = new HashMap<E,Object>(); }
    // 以指定的 initialCapacity、loadFactor 創(chuàng)建 HashSet // 其實就是以相應的參數創(chuàng)建 HashMap
    public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<E,Object>(initialCapacity, loadFactor); }
    public HashSet(int initialCapacity) {
    map = new HashMap<E,Object>(initialCapacity); }
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<E,Object>(initialCapacity , loadFactor); }
    // 調用 map 的 keySet 來返回所有的 key public Iterator<E> iterator()
    {
    return map.keySet().iterator(); }
    // 調用 HashMap 的 size() 方法返回 Entry 的數量,就得到該 Set 里元素的個數
    public int size() {
    return map.size(); }
    // 調用 HashMap 的 isEmpty() 判斷該 HashSet 是否為空, // 當 HashMap 為空時,對應的 HashSet 也為空 public boolean isEmpty() {
    return map.isEmpty(); }
    // 調用 HashMap 的 containsKey 判斷是否包含指定 key // HashSet 的所有元素就是通過 HashMap 的 key 來保存的 public boolean contains(Object o) {
    return map.containsKey(o); }
    // 將指定元素放入 HashSet 中,也就是將該元素作為 key 放入 HashMap public boolean add(E e) {
    return map.put(e, PRESENT) == null; }
    // 調用 HashMap 的 remove 方法刪除指定 Entry,也就刪除了 HashSet 中對應的元素
    public boolean remove(Object o) {
    return map.remove(o)==PRESENT; }
    // 調用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
    public void clear() {
    map.clear(); } ... }
    由上面源程序可以看出,HashSet 的實現其實只是封裝了一個 HashMap 對象來存儲所有的集合元素,所有放入 HashSet 中的集合元素實際上由 HashMap 的 key 來保存,而 HashMap 的 value 則存儲了一個 PRESENT,它是一個靜態(tài)的 Object 對象。
    HashSet 的絕大部分方法都是通過調用 HashMap 的方法來實現的,因此 HashSet 和 HashMap 兩個集合在實現本質上是相同的。
    二.HashSet<E>對象
    HashSet<E>創(chuàng)建的對象稱為集合:
    HashSet<string> s= HashSet<string>;
    那么s就是一個可以存儲 string 類型數據的集合,s 可以調用add(String s)方法將string類型的數據添加到集合中。添加到集合中的數據稱為集合的元素。集合不允許有相同的元素,也就是說,如果b已經是集合中的元素,那么在執(zhí)行set.add(b)操作是無效的。 三.HashSet<E>中的方法詳解
    ① public boolean add(E o) —— 向集合添加參數指定的元素。(如果此集合中還
    不包含指定元素,則添加指定元素。)
    參數:
    o - 將添加到此集合中的元素。 返回:
    如果該集合還不包含指定元素,則返回 true。
    ② public void clear() ——清空集合,使集合不含有任何元素。
    ③ public boolean contains(Object o) —— 判斷參數指定的數據是否屬于集合。()
    參數:
    o - 其在此集合中的存在已得到測試的元素。
    返回:
    如果此集合不包含指定元素,則返回 true。
    ④ public boolean isEmpty()—— 判斷集合是否為空。
    返回:
    如果此集合不包含任何元素,則返回 true。
    ⑤ public boolean remove(Object o) ——集合刪除參數指定的元素。
    參數:
    o - 如果存在于此集合中則需要將其移除的對象。
    返回:
    如果集合包含指定元素,則返回 true。
    ⑥ public int size () —— 返回集合中元素的個數。
    返回:
    此集合中的元素的數量(集合的容量)。
    ⑦ Object [ ] toArray() —— 將集合元素存放到數組中,并返回這個數組。
    ⑧ boolean containsAll (HashSet set) —— 判斷當前集合是否包含參數指定的集合。
    ⑨ public Object clone () —— 得到當前集合的一個克隆對象,該對象中元素的改
    變不會影響到當前集合中的元素,反之亦然。 返回:
    此集合的淺表復制。
    三.代碼:
    import java.util.HashSet;
    class Student{ String name; int score;
    Student(String name, int score){ this.name = name; this.score = score; } }
    public class TestHashSet{
    public static void main(String[] args) {
    Student zh = new Student("張三",77); Student li = new Student("李四",68); Student wa = new Student("王五",67);
    HashSet<Student> set = new HashSet<Student>(); HashSet<Student> subset = new HashSet<Student>();
    System.out.println("Before add(zh):"+set.add(zh)); set.add(zh);
    System.out.println("After add(zh):"+set.add(zh)); //add方法的實現 set.add(wa); set.add(li);
    subset.add(wa); subset.add(li);
    System.out.println("Is subset empty? "+subset.isEmpty()); //isempty方法的實現
    if (set.contains(wa)){
    System.out.println("集合set中含有:"+wa.name); //contains方法的實現 }
    if(set.containsAll(subset)){
    System.out.println("集合set包含集合subset"); }
    int number = subset.size(); //size方法的實現 System.out.println("集合subset中有"+number+"個元素:");
    Object s[] = subset.toArray(); //toArray 方法的實現
    for(int i=0; i<s.length; i++){
    System.out.printf("姓名:%s,分數:%d ", ((Student)s[i]).name,((Student)s[i]).score); }
    subset.remove(wa); //remove方法的實現 System.out.println("After implement remove on subset");
    System.out.println("集合subset中有"+subset.size()+"個元素:");
    Object a[] = subset.toArray();
    for(int i=0; i<a.length; i++){
    System.out.printf("姓名:%s,分數:%d ", ((Student)a[i]).name,((Student)a[i]).score); } } }
    四.運行結果
    Before add(zh):true After add(zh):false Is subset empty? false 集合set中含有:王五 集合set包含集合subset 集合subset中有2個元素: 姓名:李四,分數:68 姓名:王五,分數:67
    After implement remove on subset 集合subset中有1個元素: 姓名:李四,分數:68