hashset java 键值对_Java中的各个容器的性能对比
java中個個容器的屬性,性能,參數對比;
Java容器的性能及屬性的對比List:Vector,ArrayList,LinkedList
Vector:內部是數組數據結構,可以理解為加鎖的ArrayList,線程安全的,增刪,查詢都很慢。
Vector在JDK1.0版本就已經出現了,在1.2版本后出現了Collection集合,開始有集合框架,Vector改進為可以實現List接口,納入集合框架。構造函數Vector()構造一個空向量,內部數組默認初始化大小為10。Vector中的方法都是從Collection和List繼承來的。但Vector有一些特有的方法 :void addElement(E obj)
E firstElement()
E lastElement()
boolean removeElement(Object obj)
void setElementAt(E obj, int index)等…這些方法和對應不帶Element的方法功能相同。
ArrayList
ArrayList是大小可變的數組,ArrayList()構造函數默認初始化一個容量為10的空列表,如果剛開始給它開辟的內存是11,那么,它的初始化就是11的容量;
ArrayList中每一個元素都有自己的地址值,數組中存儲著這些元素的地址值,因為數組是一片連續的空間,所以在查詢某一元素的時候速度很快。但是刪除某個元素的時候,如果是刪除最后一個則很快,否則刪除的元素位置越靠前越慢,因為刪除后后面的元素都要位移前一位,查詢是根據數組的下標索引查的,所以相對于移動元素的時間很快,同樣添加元素也是一樣,越靠后越快;
LinkedList 是雙向鏈接列表數據存儲格式的,簡稱鏈表格式
鏈表中每個元素都有自己的地址,第一個元素記住第二個元素的地址,第二個元素記住第三個元素的地址,以此類推…如果想要查詢其中的某一個元素,要從第一個元素挨個做判斷,因為這些元素不是連續的,所以很慢。如果要增加一個元素,讓這個元素把地址給前一個元素,再記住后一個元素的位置即可;如果要刪除一個元素,只要它前一個元素記住它后一個元素的地址即可,所以增刪的速度很快。 增刪的速度也是相對的,LinkedList是雙向鏈表如果刪除第一個元素那是最快的,如果刪除最后一個元素也很快,同樣添加第一個元素或最后一個元素會很快.
HashSet
速度快、效率高,
不能保證元素的排列順序,順序有可能發生變化
不是同步的
集合元素可以是null,但只能放入一個null
當向HashSet集合中存入一個元素時,HashSet會調用該對象的hashCode()方法來得到該對象的hashCode值,然后根據 hashCode值來決定該對象在HashSet中存儲位置。
簡單的說,HashSet集合判斷兩個元素相等的標準是兩個對象通過equals方法比較相等,并且兩個對象的hashCode()方法返回值相 等
注意,如果要把一個對象放入HashSet中,重寫該對象對應類的equals方法,也應該重寫其hashCode()方法。其規則是如果兩個對 象通過equals方法比較返回true時,其hashCode也應該相同。另外,對象中用作equals比較標準的屬性,都應該用來計算 hashCode的值。
HashSet要求放入的對象必須實現HashCode()方法,放入的對象,是以hashcode碼作為標識的,而具有相同內容的 String對象,hashcode是一樣,所以放入的內容不能重復。但是同一個類的對象可以放入不同的實例 。
TreeSet
1、TreeSet 是二差樹實現的,Treeset中的數據是自動排好序的,不允許放入null值。
2、HashSet 是哈希表實現的,HashSet中的數據是無序的,可以放入null,但只能放入一個null,兩者中的值都不能重復,就如數據庫中唯一約束。
是一個可排序的Set,TreeSet是SortedSet接口的唯一實現類,TreeSet可以確保集合元素處于排序狀態。TreeSet支持兩種排序方式,自然排序 和定制排序,其中自然排序為默認的排序方式。向TreeSet中加入的應該是同一個類的對象。
TreeSet判斷兩個對象不相等的方式是兩個對象通過equals方法返回false,或者通過CompareTo方法比較沒有返回0
自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法來比較元素之間大小關系,然后將元素按照升序排列。
Java提供了一個Comparable接口,該接口里定義了一個compareTo(Object obj)方法,該方法返回一個整數值,實現了該接口的對象就可以比較大小。
obj1.compareTo(obj2)方法如果返回0,則說明被比較的兩個對象相等,如果返回一個正數,則表明obj1大于obj2,如果是 負數,則表明obj1小于obj2。
如果我們將兩個對象的equals方法總是返回true,則這兩個對象的compareTo方法返回應該返回0
定制排序
自然排序是根據集合元素的大小,以升序排列,如果要定制排序,應該使用Comparator接口,實現 int compare(T o1,T o2)方法。
使用場景:HashSet是基于Hash算法實現的,其性能通常都優于TreeSet。我們通常都應該使用HashSet,在我們需要排序的功能時,我們才使用TreeSet。
HashSet與TreeSet的底層運行方式: TreeSet集合對象的加入過程:
TreeSet的底層是通過二叉樹來完成存儲的,無序的集合
當我們將一個對象加入treeset中,treeset會將第一個對象作為根對象,然后調用對象的compareTo方法拿第二個對象和第一個比較,當返回至=0時,說明2個對象內容相等,treeset就不把第二個對象加入集合。返回>1時,說明第二個對象大于第一個對象,將第二個對象放在右邊,返回-1時,則將第二個對象放在左邊,依次類推
HashSet集合對象的加入過程:
Hashset底層是hash值的地址,它里面存的對象是無序的。 第一個對象進入集合時,hashset會調用object類的hashcode根據對象在堆內存里的地址調用對象重寫的hashcode計算出一個hash值,然后第一個對象就進入hashset集合中的任意一個位置。
第二個對象開始進入集合,hashset先根據第二個對象在堆內存的地址調用對象的計算出一個hash值,如果第二個對象和第一個對象在堆內存里的地址是相同的,那么得到的hash值也是相同的,直接返回true,hash得到true后就不把第二個元素加入集合(這段是hash源碼程序中的操作)。如果第二個對象和第一個對象在堆內存里地址是不同的,這時hashset類會先調用自己的方法遍歷集合中的元素,當遍歷到某個元素時,調用對象的equals方法,如果相等,返回true,則說明這兩個對象的內容是相同的,hashset得到true后不會把第二個對象加入集合。
HashMap 主要用來存放鍵值對,它基于哈希表的Map接口實現,是常用的Java集合之一,數據是無序的,jdk1.8在解決哈希沖突時有了較大的變化,當鏈表長度大于閾值(默認為8)時,將鏈表轉化為紅黑樹,以減少搜索時間。
HashMap的數組HashMap的數組的鏈表HashMap JDK1.8 之前 HashMap 由 數組+鏈表 組成的,數組是 HashMap 的主體,鏈表則是主要為了解決哈希沖突而存在的.
HashMap的時間復雜度O(1),但是如果沖突較多,鏈表的時間復雜度是O(n),所以在JDK1.8 以后,當鏈表長度大于閾值(默認為 8)時,將鏈表轉化為紅黑樹,以減少搜索時間,紅黑樹的時間復雜度是O(log n)。 所以查詢一個HashMap數據的時間為 O(1) + O(n)或O(1) + O(log n) 平均為O(1)
總結:HashMap根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度,插入、刪除和定位元素,HashMap是最好的選擇。
TreeMap
TreeMap是基于紅黑樹實現的一個保證有序性的Map 基于紅黑樹,所以TreeMap的時間復雜度是O(log n),如果需要有排序的數據,直接存放進TreeMap中就行,TreeMap自己會給排序,不需要再寫排序代碼。
總結:TreeMap取出來的是排序后的鍵值對。插入、刪除需要維護平衡會犧牲一些效率。但如果要按自然順序或自定義順序遍歷,那么TreeMap會更好。
HashMap通過hashcode對其內容進行快速查找,而 TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap。HashMap通常比TreeMap效率要高一些,一個是哈希表,一個是二叉樹,建議多使用HashMap,在需要排序的Map時候才用TreeMap。HashMap的查詢速度比TreeMap要快。
HashMap 數組鏈表的紅黑樹TreeMap 二叉樹的紅黑樹
LinkedHashSet 是具有可預知迭代順序的Set接口的哈希表和鏈接列表實現。此實現與HashSet的不同之處在于,后者維護著一個運行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,該迭代順序可為插入順序或是訪問順序。
注意,此實現不是同步的。如果多個線程同時訪問鏈接的哈希Set,而其中至少一個線程修改了該Set,則它必須保持外部同步。
LinkedHashSet:繼承于HashSet,基于LinkedHashMap來實現.底層是LinkedHashMap實現
Set接口的一個實現.和HashSet的區別,LinkedHashSet維護一個雙重鏈接列表,定義了迭代順序可為插入順序,或者是訪問順序.
CurrentHashMap 1.7與HashMap1.7非常相似,唯一的區別就是其中的核心數據如value,以及鏈表都是volatile修飾的,保證了獲取時的可見性。
ConcurrentHashMap采用了分段鎖技術,其中Segment繼承于ReetrantLock。不會像HashTable
那樣不管是put還是get操作都需要做同步處理,理論上ConcurrentHashMap支持Segment數組數量的線程并發。
每當一個線程占用鎖訪問一個Segment時,不會影響到其他的Segment。
ArrayList、Vector、HashMap、HashSet的默認初始容量、加載因子、擴容增量
當底層實現涉及到擴容時,容器或重新分配一段更大的連續內存(如果是離散分配則不需要重新分配,離散分配都是插入新元素時動態分配內存),要將容器原來的數據全部復制到新的內存上,這無疑使效率大大降低。
加載因子的系數小于等于1,意指 即當 元素個數 超過 容量長度*加載因子的系數 時,進行擴容。
另外,擴容也是有默認的倍數的,不同的容器擴容情況不同。
List 元素是有序的、可重復
ArrayList、Vector默認初始容量為10
Vector:線程安全,但速度慢
底層數據結構是數組結構
加載因子為1:即當 元素個數 超過 容量長度 時,進行擴容
擴容增量:原容量的 1倍
如 Vector的容量為10,一次擴容后是容量為20,
當初始化給11的時候,首次內存空間就是11,然后擴容的話是22,
ArrayList:線程不安全,查詢速度快
底層數據結構是數組結構
擴容增量:原容量的 0.5倍+1
如 ArrayList的容量為10,一次擴容后是容量為16
當初始化給11的時候,首次內存空間就是11,然后擴容的話是19,
Set(集) 元素無序的、不可重復。
HashSet:線程不安全,存取速度快
底層實現是一個HashMap(保存數據),實現Set接口
默認初始容量為16(為何是16,見下方對HashMap的描述)
加載因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容
擴容增量:原容量的 1 倍
如 HashSet的容量為16,一次擴容后是容量為32
構造方法摘要HashSet()
HashSet(int initialCapacity)
構造一個新的空 set,其底層 HashMap 實例具有指定的初始容量和默認的加載因子(0.75)。
HashSet hs=new HashSet(1);
所以可見 HashSet類,創建對象的時候是可以的制定容量的大小的 ,期中第二個就具有這個工功能。
Map是一個雙列集合
HashMap:默認初始容量為16
(為何是16:16是2^4,可以提高查詢效率,另外,32=16<<1 -->至于詳細的原因可另行分析,或分析源代碼)
加載因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容
擴容增量:原容量的 1 倍
如 HashSet的容量為16,一次擴容后是容量為32
理論上講ArryaList的數據是線性的,LinkedList是離散的數據,LinkedList更消耗內存,但是ArrayList有個擴容機制,就是假設ArrayList 有11條數據,那么它的內存是16,所以怎么解釋?但是數據給出的是LinkedList更消耗內存:
ArrayList和LinkedList分別在64位操作系統和32位操作系統上運行的效率未完待續...
總結
以上是生活随笔為你收集整理的hashset java 键值对_Java中的各个容器的性能对比的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于CSS3多重背景及背景图片裁剪和定位
- 下一篇: java增删改查_Java程序员你真的甘