Java集合源碼分析(六)TreeSet<E>

来源:http://www.cnblogs.com/babycomeon/archive/2016/08/03/5654105.html
-Advertisement-
Play Games

TreeSet簡介 TreeSet 是一個有序的集合,它的作用是提供有序的Set集合。它繼承於AbstractSet抽象類,實現了NavigableSet<E>, Cloneable, java.io.Serializable介面。 TreeSet 繼承於AbstractSet,所以它是一個Set集 ...


TreeSet簡介

  TreeSet 是一個有序的集合,它的作用是提供有序的Set集合。它繼承於AbstractSet抽象類,實現了NavigableSet<E>, Cloneable, java.io.Serializable介面。
  TreeSet 繼承於AbstractSet,所以它是一個Set集合,具有Set的屬性和方法。
  TreeSet 實現了NavigableSet介面,意味著它支持一系列的導航方法。比如查找與指定目標最匹配項。
  TreeSet 實現了Cloneable介面,意味著它能被克隆。
  TreeSet 實現了java.io.Serializable介面,意味著它支持序列化。

  TreeSet是基於TreeMap實現的。TreeSet中的元素支持2種排序方式:自然排序 或者 根據創建TreeSet 時提供的 Comparator 進行排序。這取決於使用的構造方法。
  TreeSet為基本操作(add、remove 和 contains)提供受保證的 log(n) 時間開銷。
  另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。

TreeSet的構造函數

// 預設構造函數。使用該構造函數,TreeSet中的元素按照自然排序進行排列。
TreeSet()

// 創建的TreeSet包含collection
TreeSet(Collection<? extends E> collection)

// 指定TreeSet的比較器
TreeSet(Comparator<? super E> comparator)

// 創建的TreeSet包含set
TreeSet(SortedSet<E> set)

TreeSet的API

boolean                   add(E object)
boolean                   addAll(Collection<? extends E> collection)
void                      clear()
Object                    clone()
boolean                   contains(Object object)
E                         first()
boolean                   isEmpty()
E                         last()
E                         pollFirst()
E                         pollLast()
E                         lower(E e)
E                         floor(E e)
E                         ceiling(E e)
E                         higher(E e)
boolean                   remove(Object object)
int                       size()
Comparator<? super E>     comparator()
Iterator<E>               iterator()
Iterator<E>               descendingIterator()
SortedSet<E>              headSet(E end)
NavigableSet<E>           descendingSet()
NavigableSet<E>           headSet(E end, boolean endInclusive)
SortedSet<E>              subSet(E start, E end)
NavigableSet<E>           subSet(E start, boolean startInclusive, E end, boolean endInclusive)
NavigableSet<E>           tailSet(E start, boolean startInclusive)
SortedSet<E>              tailSet(E start)

說明:

(01) TreeSet是有序的Set集合,因此支持add、remove、get等方法。
(02) 和NavigableSet一樣,TreeSet的導航方法大致可以區分為兩類,一類時提供元素項的導航方法,返回某個元素;另一類時提供集合的導航方法,返回某個集合。
lower、floor、ceiling 和 higher 分別返回小於、小於等於、大於等於、大於給定元素的元素,如果不存在這樣的元素,則返回 null。

TreeSet源碼分析

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

 

/*
 * @(#)TreeSet.java	1.37 06/05/10
 *
 * 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
 * @version 1.37, 05/10/06
 * @see	    Collection
 * @see	    Set
 * @see	    HashSet
 * @see     Comparable
 * @see     Comparator
 * @see	    TreeMap
 * @since   1.2
 */

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    /**
     * NavigableMap對象
     */
    private transient NavigableMap<E,Object> m;

    // TreeSet是通過TreeMap實現的,
    // PRESENT是鍵-值對中的值。
    private static final Object PRESENT = new Object();

    /**
     * 將TreeMap賦值給 "NavigableMap對象m"
     */
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    /**
     * 不帶參數的構造函數。創建一個空的TreeMap
     */
    public TreeSet() {
	this(new TreeMap<E,Object>());
    }

    /**
     * 帶比較器的構造函數。
     */
    public TreeSet(Comparator<? super E> comparator) {
	this(new TreeMap<E,Object>(comparator));
    }

    /**
     * 創建TreeSet,並將集合c中的全部元素都添加到TreeSet中
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * 創建TreeSet,並將s中的全部元素都添加到TreeSet中
     */
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
	addAll(s);
    }

    /**
     * 返回TreeSet的順序排列的迭代器。
     * 因為TreeSet是TreeMap實現的,所以這裡實際上時返回TreeMap的“鍵集”對應的迭代器
     */
    public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

    /**
     * 返回TreeSet的逆序排列的迭代器。
     * 因為TreeSet是TreeMap實現的,所以這裡實際上時返回TreeMap的“鍵集”對應的迭代器
     */
    public Iterator<E> descendingIterator() {
	return m.descendingKeySet().iterator();
    }

    /**
     * 返回NavigableSet<E>類型的TreeSet
     */
    public NavigableSet<E> descendingSet() {
	return new TreeSet(m.descendingMap());
    }

    /**
     * 返回大小
     */
    public int size() {
	return m.size();
    }

    /**
     * 是否為空
     */
    public boolean isEmpty() {
	return m.isEmpty();
    }

    /**
     * 是否包含o
     */
    public boolean contains(Object o) {
	return m.containsKey(o);
    }

    /**
     * 添加元素e
     */
    public boolean add(E e) {
	return m.put(e, PRESENT)==null;
    }

    /**
     * 刪除元素o
     */
    public boolean remove(Object o) {
	return m.remove(o)==PRESENT;
    }

    /**
     * 清空集合
     */
    public void clear() {
	m.clear();
    }

    /**
     * 將集合c中的全部元素添加到TreeSet中
     */
    public  boolean addAll(Collection<? extends E> c) {
        // Use linear-time version if applicable
        if (m.size()==0 && c.size() > 0 &&
	    c instanceof SortedSet &&
            m instanceof TreeMap) {
            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
            Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
            Comparator<? super E> mc = map.comparator();
            if (cc==mc || (cc != null && cc.equals(mc))) {
                map.addAllForTreeSet(set, PRESENT);
                return true;
            }
        }
        return super.addAll(c);
    }

    /**
     * 返回子Set,實際上是通過TreeMap的subMap()實現的。
     */
    public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                                  E toElement,   boolean toInclusive) {
	return new TreeSet<E>(m.subMap(fromElement, fromInclusive,
                                       toElement,   toInclusive));
    }

    /**
     * 返回Set的頭部,範圍是:從頭部到toElement。
     * inclusive是是否包含toElement的標誌
     */
    public NavigableSet<E> headSet(E toElement, boolean inclusive) {
	return new TreeSet<E>(m.headMap(toElement, inclusive));
    }

    /**
     * 返回Set的尾部,範圍是:從fromElement到結尾。
     * inclusive是是否包含fromElement的標誌
     */
    public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
	return new TreeSet<E>(m.tailMap(fromElement, inclusive));
    }

    /**
     * 返回子Set。範圍是:從fromElement(包括)到toElement(不包括)。
     */
    public SortedSet<E> subSet(E fromElement, E toElement) {
	return subSet(fromElement, true, toElement, false);
    }

    /**
     * 返回Set的頭部,範圍是:從頭部到toElement(不包括)。
     */
    public SortedSet<E> headSet(E toElement) {
	return headSet(toElement, false);
    }

    /**
     * 返回Set的尾部,範圍是:從fromElement到結尾(不包括)。
     */
    public SortedSet<E> tailSet(E fromElement) {
	return tailSet(fromElement, true);
    }
    
    // 返回Set的比較器
    public Comparator<? super E> comparator() {
        return m.comparator();
    }

    /**
     * 返回Set的第一個元素
     */
    public E first() {
        return m.firstKey();
    }

    /**
     * 返回Set的最後一個元素
     */
    public E last() {
        return m.lastKey();
    }

    // NavigableSet API methods

    /**
     * 返回Set中小於e的最大元素
     */
    public E lower(E e) {
        return m.lowerKey(e);
    }

    /**
     * 返回Set中小於/等於e的最大元素
     */
    public E floor(E e) {
        return m.floorKey(e);
    }

    /**
     * 返回Set中大於/等於e的最小元素
     */
    public E ceiling(E e) {
        return m.ceilingKey(e);
    }

    /**
     * 返回Set中大於e的最小元素
     */
    public E higher(E e) {
        return m.higherKey(e);
    }

    /**
     * 獲取第一個元素,並將該元素從TreeMap中刪除。
     */
    public E pollFirst() {
        Map.Entry<E,?> e = m.pollFirstEntry();
        return (e == null)? null : e.getKey();
    }

    /**
     * 獲取最後一個元素,並將該元素從TreeMap中刪除。
     */
    public E pollLast() {
        Map.Entry<E,?> e = m.pollLastEntry();
        return (e == null)? null : e.getKey();
    }

    /**
     * 克隆一個TreeSet,並返回Object對象
     */
    public Object clone() {
        TreeSet<E> clone = null;
	try {
	    clone = (TreeSet<E>) super.clone();
	} catch (CloneNotSupportedException e) {
	    throw new InternalError();
	}

        clone.m = new TreeMap<E,Object>(m);
        return clone;
    }

    /**
     * java.io.Serializable的寫入函數
     * 
     * 將TreeSet的“比較器、容量,所有的元素值”都寫入到輸出流中
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
	// Write out any hidden stuff
	s.defaultWriteObject();

        // 寫入比較器
        s.writeObject(m.comparator());

        // 寫入容量
        s.writeInt(m.size());

	// 寫入“TreeSet中的每一個元素”
	for (Iterator i=m.keySet().iterator(); i.hasNext(); )
            s.writeObject(i.next());
    }

    /**
     * java.io.Serializable的讀取函數:根據寫入方式讀出
     * 先將TreeSet的“比較器、容量、所有的元素值”依次讀出
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
	// Read in any hidden stuff
	s.defaultReadObject();

        // 從輸入流中讀取TreeSet的“比較器”
        Comparator<? super E> c = (Comparator<? super E>) s.readObject();

        // Create backing TreeMap
	TreeMap<E,Object> tm;
	if (c==null)
	    tm = new TreeMap<E,Object>();
	else
	    tm = new TreeMap<E,Object>(c);
	m = tm;

        // 從輸入流中讀取TreeSet的“容量”
        int size = s.readInt();
        // 從輸入流中讀取TreeSet的“全部元素”
        tm.readTreeSet(size, s, PRESENT);
    }
    // TreeSet的序列版本號
    private static final long serialVersionUID = -2479143000061671589L;
}

 

總結:

(01) TreeSet實際上是TreeMap實現的。當我們構造TreeSet時;若使用不帶參數的構造函數,則TreeSet的使用自然比較器;若用戶需要使用自定義的比較器,則需要使用帶比較器的參數。
(02) TreeSet是非線程安全的。
(03) TreeSet實現java.io.Serializable的方式。當寫入到輸出流時,依次寫入“比較器、容量、全部元素”;當讀出輸入流時,再依次讀取。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Standford Moss 系統是斯坦福大學大名鼎鼎的代碼查重系統,它可以查出哪些同學提交的代碼是抄襲別人的,從而將提交結果拒之門外。它對一切希望使用該系統的人都是開放的,那麼在PHP的項目中如何使用它呢? 下載Moss的PHP文件moss.php 您可以訪問https://github.com/ ...
  • Eclipse註釋規範模版總結 一、具體操作 (1)在eclipse中,打開Window->Preference->Java->Code Style->Code Template (2)然後展開Comments節點就是所有需設置註釋的元素,參照下麵註釋規範對應設置即可 ...
  • 多態是同一個行為具有多個不同表現形式或形態的能力。多態性是對象多種表現形式的體現。 多態存在的三個必要條件: 繼承 重寫 父類引用指向子類對象 例:Parent p = new Child(); 當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去調用子類的同名方 ...
  • 一、問題背景 整數拆分,指把一個整數分解成若幹個整數的和 如 3=2+1=1+1+1 共2種拆分 我們認為2+1與1+2為同一種拆分 二、定義 在整數n的拆分中,最大的拆分數為m,我們記它的方案數為 f(n,m) 即 n=x1+x2+······+xk-1+xk ,任意 x≤m 在此我們採用遞歸遞推 ...
  • 一、數據類型 Python3 中有六個標準的數據類型: Number(數字) String(字元串) List(列表) Tuple(元組) Sets(集合) Dictionary(字典) Python3 支持 int(整形)、float(浮點型)、bool(布爾型)、complex(複數)。在Pyt ...
  • 如何修改nginx預設的名稱,可以稍微的偽裝一下,也可以裝x 一般來說修改3個位置,一個是nginx.h、另一個是ngx_http_header_filter_module.c、還有一個ngx_http_special_response.c。 提示:一般修改都是在nginx編譯之前修改,修改完了之後 ...
  • 插入排序法基本原理 插入排序法較冒泡排序法和選擇排序法更貼近生活,應該來說理解起來更快。如果你現在能夠得到一副麻將,請把裡面的“一萬”到“六萬”拿出來,打亂順序,再重新排好,就像打麻將開始那樣。是否需要拿出某個麻將拿出來再插入其它麻將之間?這就是插入排序了。不過電腦沒有你那麼聰明,你只要小小幾步就 ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...