1. 程式人生 > >java提高篇(二四)-----HashSet

java提高篇(二四)-----HashSet

      原文出自:http://cmsblogs.com/?p=599

      在前篇博文中(java提高篇(二三)-----HashMap)詳細講解了HashMap的實現過程,對於HashSet而言,它是基於HashMap來實現的,底層採用HashMap來儲存元素。所以如果對HashMap比較熟悉,那麼HashSet是so easy!!

一、定義

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

       HashSet繼承AbstractSet類,實現Set、Cloneable、Serializable介面。其中AbstractSet提供 Set 介面的骨幹實現,從而最大限度地減少了實現此介面所需的工作。Set介面是一種不包括重複元素的Collection,它維持它自己的內部排序,所以隨機訪問沒有任何意義。

基本屬性

//基於HashMap實現,底層使用HashMap儲存所有元素
private transient HashMap<E,Object> map;

 //定義一個Object物件作為HashMap的value
 private static final Object PRESENT = new Object();

建構函式

/**
         * 預設建構函式
         * 初始化一個空的HashMap,並使用預設初始容量為16和載入因子0.75。
         */
        public HashSet() {
            map = new HashMap<>();
        }
        
        /**
         * 構造一個包含指定 collection 中的元素的新 set。
         */
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
        
        /**
         * 構造一個新的空 set,其底層 HashMap 例項具有指定的初始容量和指定的載入因子
         */
        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
           
        /**
         * 構造一個新的空 set,其底層 HashMap 例項具有指定的初始容量和預設的載入因子(0.75)。
         */
        public HashSet(int initialCapacity) {
           map = new HashMap<>(initialCapacity);
        }
           
        /**
         * 在API中我沒有看到這個建構函式,今天看原始碼才發現(原來訪問許可權為包許可權,不對外公開的)
         * 以指定的initialCapacity和loadFactor構造一個新的空連結雜湊集合。
         * dummy 為標識 該建構函式主要作用是對LinkedHashSet起到一個支援作用
         */
        HashSet(int initialCapacity, float loadFactor, boolean dummy) {
           map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }

從建構函式中可以看出HashSet所有的構造都是構造出一個新的HashMap,其中最後一個建構函式,為包訪問許可權是不對外公開,僅僅只在使用LinkedHashSet時才會發生作用。

二、方法

既然HashSet是基於HashMap,那麼對於HashSet而言,其方法的實現過程是非常簡單的。

public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

iterator()方法返回對此 set 中元素進行迭代的迭代器。返回元素的順序並不是特定的。底層呼叫HashMap的keySet返回所有的key,這點反應了HashSet中的所有元素都是儲存在HashMap的key中,value則是使用的PRESENT物件,該物件為static final。

public int size() {
        return map.size();
    }

size()返回此 set 中的元素的數量(set 的容量)。底層呼叫HashMap的size方法,返回HashMap容器的大小。

public boolean isEmpty() {
        return map.isEmpty();
    }

isEmpty(),判斷HashSet()集合是否為空,為空返回 true,否則返回false

public boolean contains(Object o) {
        return map.containsKey(o);
    }

contains(),判斷某個元素是否存在於HashSet()中,存在返回true,否則返回false。更加確切的講應該是要滿足這種關係才能返回true:(o==null ? e==null : o.equals(e))。底層呼叫containsKey判斷HashMap的key值是否為空。

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

add()如果此 set 中尚未包含指定元素,則新增指定元素。如果此Set沒有包含滿足(e==null ? e2==null : e.equals(e2)) 的e2時,則將e2新增到Set中,否則不新增且返回false。由於底層使用HashMap的put方法將key = e,value=PRESENT構建成key-value鍵值對,當此e存在於HashMap的key中,則value將會覆蓋原有value,但是key保持不變,所以如果將一個已經存在的e元素新增中HashSet中,新新增的元素是不會儲存到HashMap中,所以這就滿足了HashSet中元素不會重複的特性。

public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

remove如果指定元素存在於此 set 中,則將其移除。底層使用HashMap的remove方法刪除指定的Entry。

public void clear() {
        map.clear();
    }

clear從此 set 中移除所有元素。底層呼叫HashMap的clear方法清除所有的Entry。

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();
        }
    }

clone返回此 HashSet 例項的淺表副本:並沒有複製這些元素本身。

後記:

由於HashSet底層使用了HashMap實現,使其的實現過程變得非常簡單,如果你對HashMap比較瞭解,那麼HashSet簡直是小菜一碟。有兩個方法對HashMap和HashSet而言是非常重要的,下篇將詳細講解hashcode和equals。

---------------------------------------------------------------------------------------------------------

      原文出自:http://cmsblogs.com/?p=599

      關注我的個人站點:http://www.cmsblogs.com

相關推薦

java提高-----HashSet

      原文出自:http://cmsblogs.com/?p=599      在前篇博文中(java提高篇(二三)-----HashMap)詳細講解了HashMap的實現過程,對於HashSet

java提高-----HashMap

      HashMap也是我們使用非常多的Collection,它是基於雜湊表的 Map 介面的實現,以key-value的形式存在。在HashMap中,key-value總是會當做一個整體來處理,系統會根據hash演算法來來計算key-value的儲存位置,我們總是可以通過key快速地存、取value。

Java提高三五-----Java集合細節:請為集合指定初始容量

        集合是我們在Java程式設計中使用非常廣泛的,它就像大海,海納百川,像萬能容器,盛裝萬物,而且這個大海,萬能容器還可以無限變大(如果條件允許)。當這個海、容器的量變得非常大的時候,它的初

java提高-----抽象類與介面

介面和內部類為我們提供了一種將介面與實現分離的更加結構化的方法。        抽象類與介面是java語言中對抽象概念進行定義的兩種機制,正是由於他們的存在才賦予java強大的面向物件的能力。他們兩者之間對抽象概念的支援有很大的相似,甚至可以互換,但是也有區別。   

Java提高:內部類和匿名內部類

1 public class innerclass { 2 public static void main(String[] args) { 3 System.out.println("下面是是內部類的程式展示"); 4 //建立外部類和內部類的方法有點不相同

java提高-----實現多重繼承

       多重繼承指的是一個類可以同時從多於一個的父類那裡繼承行為和特徵,然而我們知道Java為了保證資料安全,它只允許單繼承。有些時候我們會認為如果系統中需要使用多重繼承往往都是糟糕的設計,這個

java提高-----詳解匿名內部類

       在java提高篇-----詳解內部類中對匿名內部類做了一個簡單的介紹,但是內部類還存在很多其他細節問題,所以就衍生出這篇部落格。在這篇部落格中你可以瞭解到匿名內部類的使用、匿名內部類要注

java提高-----詳解內部類

      可以將一個類的定義放在另一個類的定義內部,這就是內部類。        內部類是一個非常有用的特性但又比較難理解使用的特性(鄙人到現在都沒有怎麼使用過內部類,對內部類也只是略知一二)。

Java提高:實現多重繼承

public class Son { /** * 內部類繼承Father類 */ class Father_1 extends Father{ public int strong(){ return super.stron

Java提高:區分引用變數與物件

我們有程式碼: New A=new New(); 下面是這個New的類: class New { public New() { System.out.println

Java提高二七-----TreeMap

一、為跟節點若新插入的節點N沒有父節點,則直接當做根據節點插入即可,同時將顏色設定為黑色。(如圖一(1))二、父節點為黑色這種情況新節點N同樣是直接插入,同時顏色為紅色,由於根據規則四它會存在兩個黑色的葉子節點,值為null。同時由於新增節點N為紅色,所以通過它的子節點的路徑依然會儲存著相同的黑色節點數,同樣

SpringMVC提高: 處理器方法支援的方法引數和返回型別

1. 支援的方法引數型別    (1 )HttpServlet 物件,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 物件。 這些引數Spring 在呼叫處理器方法的時候會自動給它們賦值,所以當在處理器方法中

java提高-----強制型別轉換

       在java中強制型別轉換分為基本資料型別和引用資料型別兩種,這裡我們討論的後者,也就是引用資料型別的強制型別轉換。 在Java中由於繼承和向上轉型,子類可以非常自然地轉換成父類,但是父類

java提高拓展 java知識彙總---IO流的使用規律總結含程式碼示例淺顯易懂

IO流的使用規律總結。 解決的問題,就是在開發過程中具體要使用哪個流物件的問題。 1,明確 資料來源,資料匯(資料的目的)其實就是在明確要使用的IO體系,InputStream OutputStream Reader Writer需求中操作的是源:意味著是 讀。InputS

Java資料結構—— 平衡叉樹AVL樹

平衡二叉樹(AVL樹) 二叉排序樹問題分析 左子樹全部為空,從形式上看更像一個單鏈表 插入速度沒有影響 查詢速度明顯降低 解決方案:平衡二叉樹 基本介紹 平衡二叉樹也叫二叉搜尋樹,保證查詢效率較高 它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩棵子樹都是一棵平衡

Java學習筆記十三:final關鍵字

類繼承 ron 滿足 單詞 靜態 bsp 條件 str 進行 final關鍵字有三種使用場景: final修飾類 final修飾方法 final修飾變量 final修飾的類,不能再有子類繼承。 只要滿足以下條件就可以把一個類設計為final類: 不是專門為繼承而設

Java學習總結——java反射機制,利用反射動態創建對象

Java反射 動態創建對象 一.Java反射機制1.什麽是反射:反射就是把Java類中的各種成份影射成一個個的Java對象。例:一個類有:成員變量,方法,構造方法等,包等等信息,利用反射技術可以對一個類進行剖析,把各個組成部分影射成一個個對象。2.Java反射常用類:(1)Class類—可獲取類和類的

Java學習總結十三——前端:HTML基本標簽的使用

water 默認值 right 列表框 信息工程 area led mea MF 一.HTML概述1.HTML:(Hyper Text Markup Language)超文本標記語言,是一種專門用於創建Web超文本文檔的編程語言,它能告訴Web瀏覽程序如何顯示Web文檔(即

Spring Boot + Spring Cloud 實現許可權管理系統 後端:服務熔斷Hystrix、Turbine

線上演示 演示地址:http://139.196.87.48:9002/kitty 使用者名稱:admin 密碼:admin 雪崩效應 在微服務架構中,由於服務眾多,通常會涉及多個服務層級的呼叫,而一旦基礎服務發生故障,很可能會導致級聯故障,進而造成整個系統不可用,這種現象被稱為服務雪崩效應。服務雪崩

Java開發筆記一維陣列的用法

之前介紹的各類變數都是單獨宣告的,倘若要求定義相同型別的一組變數,則需定義許多同類型的變數,顯然耗時耗力且不宜維護。為此,程式語言引入了陣列的概念,每個陣列都由一組相同型別的資料構成,對外有統一的陣列名稱,對內通過序號區分每個資料元素。陣列型別由基本的變數型別擴充套件而來,在基本型別後面加上一對方括號,便形成