終于,我讀懂了所有Java集合——set篇

HashSet

(底層是HashMap)

Set不允許元素重復。

基于HashMap實現,無容量限制。

是非線程安全的。

成員變量

private transient HashMap<E,Object> map;

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

?

構造方法

/*** Constructs a new, empty set; the backing <tt>HashMap</tt> instance has* default initial capacity (16) and load factor (0.75).*/
public HashSet() {map = new HashMap<>();
}
public HashSet(int initialCapacity) {map = new HashMap<>(initialCapacity);
}
public HashSet(int initialCapacity, float loadFactor) {map = new HashMap<>(initialCapacity, loadFactor);
}

添加

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

刪除

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

?

遍歷

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

?

包含

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

?

TreeSet

(底層是TreeMap)

基于TreeMap實現,支持排序(自然排序?或者?根據創建TreeSet 時提供的 Comparator 進行排序)。

是非線程安全的。

?

成員變量

/**
?* The backing map.
?*/

private transient NavigableMap<E,Object> m;

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

?

構造方法

public TreeSet() {this(new TreeMap<E,Object>());
}public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));
}

?

添加

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

刪除

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

遍歷

public Iterator<E> iterator() {return m.navigableKeySet().iterator();
}

包含

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

獲取開頭

public E first() {return m.firstKey();
}

獲取結尾

public E last() {return m.lastKey();
}

子集

public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,E toElement,?? boolean toInclusive) {return new TreeSet<>(m.subMap(fromElement, fromInclusive,toElement,?? toInclusive));
}

默認是含頭不含尾

public SortedSet<E> subSet(E fromElement, E toElement) {return subSet(fromElement, true, toElement, false);
}

LinkedHashSet

(繼承自HashSet,底層是LinkedHashMap)

LinkedHashSet繼承自HashSet,源碼更少、更簡單,唯一的區別是LinkedHashSet內部使用的是LinkHashMap。這樣做的意義或者好處就是LinkedHashSet中的元素順序是可以保證的,也就是說遍歷序和插入序是一致的

類聲明

public class LinkedHashSet<E>
??? extends HashSet<E>
??? implements Set<E>, Cloneable, java.io.Serializable {}

構造方法

public LinkedHashSet(int initialCapacity, float loadFactor) {super(initialCapacity, loadFactor, true);
}/*** Constructs a new, empty linked hash set with the specified initial* capacity and the default load factor (0.75).** @param?? initialCapacity?? the initial capacity of the LinkedHashSet* @throws? IllegalArgumentException if the initial capacity is less*????????????? than zero*/
public LinkedHashSet(int initialCapacity) {super(initialCapacity, .75f, true);
}/*** Constructs a new, empty linked hash set with the default initial* capacity (16) and load factor (0.75).*/
public LinkedHashSet() {super(16, .75f, true);
}

?

super指的是HashSet的default訪問級別的構造方法

/*** Constructs a new, empty linked hash set.? (This package private* constructor is only used by LinkedHashSet.) The backing* HashMap instance is a LinkedHashMap with the specified initial* capacity and the specified load factor.** @param????? initialCapacity?? the initial capacity of the hash map* @param????? loadFactor??????? the load factor of the hash map* @param????? dummy???????????? ignored (distinguishes this*???????????? constructor from other int, float constructor.)* @throws???? IllegalArgumentException if the initial capacity is less*???????????? than zero, or if the load factor is nonpositive*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

BitSet

(位集,底層是long數組,用于替代List<Boolean>)

BitSet是位操作的對象,值只有0或1即false和true,內部維護了一個long數組,初始只有一個long,所以BitSet最小的size是64(8個字節64個位,可以存儲64個數字),當隨著存儲的元素越來越多,BitSet內部會動態擴充,最終內部是由N個long來存儲,這些針對操作都是透明的。

默認情況下,BitSet的所有位都是false即0。

不是線程安全的。

用1位來表示一個數據是否出現過,0為沒有出現過,1表示出現過。使用的時候既可根據某一個是否為0表示,此數是否出現過。

一個1GB的空間,有8*1024*1024*1024 = 8.58*10^9bit,也就是1GB的空間可以表示85億多個數。

常見的應用是那些需要對海量數據進行一些統計工作的時候,比如日志分析、用戶數統計等等,如統計40億個數據中沒有出現的數據,將40億個不同數據進行排序,海量數據去重等等。

JDK選擇long數組作為BitSet的內部存儲結構是出于性能的考慮,因為BitSet提供and和or這種操作,需要對兩個BitSet中的所有bit位做and或者or,實現的時候需要遍歷所有的數組元素。使用long能夠使得循環的次數降到最低,所以Java選擇使用long數組作為BitSet的內部存儲結構。

去重示例

public static void containChars(String str) {BitSet used = new BitSet();for (int i = 0; i < str.length(); i++)used.set(str.charAt(i)); // set bit for char?StringBuilder sb = new StringBuilder();sb.append("[");int size = used.size();for (int i = 0; i < size; i++) {if (used.get(i)) {sb.append((char) i);}}sb.append("]");System.out.println(sb.toString());
}public static void main(String[] args) {containChars("abcdfab");
}

?[abcdf]

排序示例

public static void sortArray(int[] array) {BitSet bitSet = new BitSet(2 << 13);// 雖然可以自動擴容,但盡量在構造時指定估算大小,默認為64?System.out.println("BitSet size: " + bitSet.size());for (int i = 0; i < array.length; i++) {bitSet.set(array[i]);}//剔除重復數字后的元素個數?int bitLen = bitSet.cardinality();//進行排序,即把bit為true的元素復制到另一個數組?int[] orderedArray = new int[bitLen];int k = 0;for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {orderedArray[k++] = i;}System.out.println("After ordering: ");for (int i = 0; i < bitLen; i++) {System.out.print(orderedArray[i] + "\t");}
}public static void main(String[] args) {int[] array = new int[]{423, 700, 9999, 2323, 356, 6400, 1, 2, 3, 2, 2, 2, 2};sortArray(array);
}

BitSet size: 16384

After ordering:

1???? 2???? 3???? 356 423 700 2323????? 6400????? 9999

CopyOnWriteArraySet

(底層是CopyOnWriteArrayList)

基于CopyOnWriteArrayList實現,其唯一的不同是在add時調用的是CopyOnWriteArrayList的addIfAbsent方法。

在每次add的時候都要進行數組的遍歷,因此其性能會略低于CopyOnWriteArrayList。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444811.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444811.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444811.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

加速scp傳輸速度

當需要在機器之間傳輸400GB文件的時候&#xff0c;你就會非常在意傳輸的速度了。默認情況下(約125MB帶寬&#xff0c;網絡延遲17ms&#xff0c;Intel E5-2430&#xff0c;本文后續討論默認是指該環境)&#xff0c;scp的速度約為40MB&#xff0c;傳輸400GB則需要170分鐘&#xf…

tcpcopy使用方法

1、下載tcpcopy http://code.google.com/p/tcpcopy/downloads/list 2、配置、編譯、安裝 依此使用如下命令&#xff1a; 配置&#xff1a; ./configure 編譯&#xff1a; make 安裝&#xff1a; make install 3、使用方法 下面以mosquitto為例&#xff0c;說明tcpcopy的用法&a…

C++(14)--面向對象

面向對象1.面向對象編程(難點)2.類和對象demo1:地主類的實現版本1demo2:地主類的實現版本23.訪問修飾符demo3:外部修改成員變量不安全(版本3)demo4: 使用封裝防止直接修改成員變量&#xff08;版本3&#xff09;demo5:進一步封裝&#xff1a;設置/獲取名字&#xff0c;修改積分…

終于,我讀懂了所有Java集合——map篇(多線程)

多線程環境下的問題 1.8中hashmap的確不會因為多線程put導致死循環&#xff08;1.7代碼中會這樣子&#xff09;&#xff0c;但是依然有其他的弊端&#xff0c;比如數據丟失等等。因此多線程情況下還是建議使用ConcurrentHashMap。 數據丟失&#xff1a;當多線程put的時候&…

system函數的返回值和執行腳本的返回值

1、先統一兩個說法&#xff1a;&#xff08;1&#xff09;system返回值&#xff1a;指調用system函數后的返回值&#xff0c;比如上例中status為system返回值&#xff08;2&#xff09;shell返回值&#xff1a;指system所調用的shell命令的返回值&#xff0c;比如上例中&#x…

OJ匯總

國內&#xff1a;&#xff08;一下排名不分先后&#xff09; 浙江大學&#xff08;ZJU&#xff09;&#xff1a;http://acm.zju.edu.cn/ 北京大學&#xff08;PKU&#xff09;&#xff1a;http://acm.pku.edu.cn/JudgeOnline/ 同濟大學&#xff08;TJU&#xff09;&#xff1a;…

C++(15)--面向對象編程實踐-歡樂斗地主(vector的花式輸出)

面向對象編程實踐-歡樂斗地主《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------要求&#xff1a;實現錄入及…

Google Protobuf 使用介紹

直接在 www.google.com.hk 上搜索google protobuf 后下載官方版本。 官方版本支持C\Java\Python三門語言。 還有很多非官方的語言版本支持&#xff0c;如C\NET(C#/Vb.net)\Flex(AS3)等. 要通信&#xff0c;必須有協議&#xff0c;否則雙方無法理解對方的碼流。在protobuf中&…

epoll的再次認識

使用mmap加速內核與用戶空間的消息傳遞。 這 點實際上涉及到epoll的具體實現了。無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很 重要,在這點上,epoll是通過內核于用戶空間mmap同一塊內存實現的。而如果你想我一樣從2.5內核就關…

leetcode82. 刪除排序鏈表中的重復元素 II

給定一個排序鏈表&#xff0c;刪除所有含有重復數字的節點&#xff0c;只保留原始鏈表中 沒有重復出現 的數字。 示例 1: 輸入: 1->2->3->3->4->4->5 輸出: 1->2->5 示例 2: 輸入: 1->1->1->2->3 輸出: 2->3 思路&#xff1a;判斷n…

C++(16)--運算符重載(自定義Integer類)

運算符重載1.運算符重載--重點2.友元函數--難點(流運算符重載)《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》 -------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)--------…

反應器組件 ACE_Reactor

6.1 反應器組件 ACE_Reactor反應器的基本原理是: 針對關心的某個事件寫一個事件處理器(event_handler). 將該事件處理器登記到反應器中(同時指明關心的事件). 然后反應器會自動檢測事件的發生. 并調用預先登記的事件處理器中的回調函數. 所以ACE Reactor 框架的責任&#x…

C++(17)--詳解const

詳解const《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------1.const修飾成員變量 2.const修飾函數參數 3.c…

cppcheck的安裝和使用

首先從這里下載linux版本的:http://sourceforge.net/projects/cppcheck/files/cppcheck/ 然后下載對應的版本,解壓,之后安裝: 編譯: g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp 安裝: make install

leetcode24 兩兩交換鏈表中的節點

給定一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后的鏈表。 你不能只是單純的改變節點內部的值&#xff0c;而是需要實際的進行節點交換。 示例: 給定 1->2->3->4, 你應該返回 2->1->4->3. 思路&#xff1a;這一看就是個遞歸定義&…

再議指針和引用的一些事情吧

關于指針和引用一直是學習C++的同學們爭論的焦點,什么時候用指針,什么時候用引用,還有怎么引用數組,這么用指針訪問數組,以及初始化的問題。 不過有一些文章我在很早就已經寫過,但是由于當時時間不充分,自己也都是隨性寫的,可以參看以前我的一個文章:http://blog.csd…

C++(18)--復制構造函數

復制構造函數《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------包裝基本類&#xff0c;封裝一些算法。 需求…

lua與C++粘合層框架

一. lua調用C 在lua中是以函數指針的形式調用函數, 并且所有的函數指針都必須滿足如下此種類型: typedef int (*lua_CFunction) (lua_State *L);   也就是說, 偶們在C中定義函數時必須以lua_State為參數, 以int為返回值才能被Lua所調用. 但是不要忘記了, 偶們的lua_State是…

leetcode147 對鏈表進行插入排序

丟人&#xff0c;我就是按插入排序老老實實寫的啊。。。。 別人肯定map了hhh。 對鏈表進行插入排序。 插入排序的動畫演示如上。從第一個元素開始&#xff0c;該鏈表可以被認為已經部分排序&#xff08;用黑色表示&#xff09;。 每次迭代時&#xff0c;從輸入數據中移除一個…

PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders

conditional Image generation with PixelCNN DecodersICML的best paperpixel cnn 屬于完全可見的信念網絡&#xff0c;需要對 概率密度 建模。給定圖像數據x&#xff0c;想要對概率分布p(x)建模。概率分布p(x)可以看做&#xff0c;每一像素分布同時作用結果的一個聯合分布。一…