Ⅰ java中常用的集合介面有哪些
集合主要有Collection和Map介面。
List特點:元素有放入順序,元素可重復
Map特點:元素按鍵值對存儲,無放入順序
Set特點:元素無放入順序,元素不可重復(注意:元素雖然無放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實是固定的)
List介面有三個實現類:LinkedList,ArrayList,Vector
LinkedList:底層基於鏈表實現,鏈表內存是散亂的,每一個元素存儲本身內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢
ArrayList和Vector的區別:ArrayList是非線程安全的,效率高;Vector是基於線程安全的,效率低
Set介面有兩個實現類:HashSet(底層由HashMap實現),LinkedHashSet
SortedSet介面有一個實現類:TreeSet(底層由平衡二叉樹實現)
Query介面有一個實現類:LinkList
Map介面有三個實現類:HashMap,HashTable,LinkeHashMap
HashMap非線程安全,高效,支持null;HashTable線程安全,低效,不支持null
SortedMap有一個實現類:TreeMap
其實最主要的是,list是用來處理序列的,而set是用來處理集的。Map是知道的,存儲的是鍵值對
set 一般無序不重復.map kv 結構 list 有序 。
Ⅱ Java集合詳解1:ArrayList,Vector與Stack
本文深入探討了Java集合類中的三個主要實例:ArrayList、Vector和Stack。它們在存儲和組織數據方面扮演著關鍵角色,尤其在實現列表操作時提供了靈活性和效率。下面,我們將詳細解析這些集合類的特性、底層實現以及性能考量。
ArrayList作為動態數組的實現,提供了一系列操作來存儲和管理數據。其核心特點在於可變的容量,通過內部數組來存儲元素,初始容量為10,並隨添加元素自動擴展。擴容時,ArrayList採用線性增長策略,將容量增加為原有容量的1.5倍。這種策略在確保性能的同時,避免了過度分配導致的內存浪費。確保容量增長的同時,通過調用ensureCapacity方法預先增加容量,可以減少多次擴容帶來的性能開銷。值得注意的是,ArrayList不是線程安全的,因此在多線程環境下訪問或修改列表時需要外部同步。
Vector則提供了一種同步的、可動態擴展的數組實現。它不僅繼承自AbstractList,還實現了RandomAccess介面,支持快速隨機訪問。Vector的擴容機制與ArrayList類似,但採用了增長因子策略來調整容量,增長因子的設定決定了每次擴容時容量的增量。此外,Vector在序列化時會復制整個數組,與ArrayList不同。Vector同樣不是線程安全的,但在內部通過同步機制確保了對Vector的並發訪問安全。
Stack類則基於Vector擴展,專為後進先出(LIFO)操作而設計。它通過一系列方法如empty()、peek()、pop()和push()提供了堆棧功能的實現。Stack繼承Vector的特性,通過簡單構造方法和方法實現提供了堆棧功能,但其源碼並未詳細展開。
在比較這三個集合類時,我們可以總結出以下關鍵區別:
1. **線程安全性**:ArrayList為非線程安全集合,而Vector提供了線程安全保證。
2. **性能**:ArrayList在隨機訪問和順序添加時表現出色,但刪除操作可能導致性能開銷;Vector和Stack在這些方面與ArrayList類似,但Vector提供了額外的同步機制。
3. **容量管理**:ArrayList採用1.5倍的線性增長策略,而Vector通過增長因子進行容量調整。
4. **同步機制**:Vector通過同步機制確保多線程環境下的安全性,而ArrayList需要外部同步來避免並發問題。
綜上所述,選擇哪個集合類取決於特定的應用需求。對於要求線程安全、頻繁隨機訪問或需要更靈活容量管理的應用場景,Vector可能更為合適。而對於性能敏感且不需要線程安全的應用,ArrayList提供了高效且簡單的數據存儲解決方案。Stack則專用於實現棧結構的特定應用需求。在實際開發中,應根據具體場景選擇最適合的集合類以實現最優性能和資源利用。
Ⅲ JAVA中的List、Vector、ArrayList的差異
Java 中Vector、ArrayList和LinkedList 的區別Java 中Vector、ArrayList和LinkedList 的區別SDK提供了有序集合介面java.util.List的幾種實現,其中三種最為人們熟知的是Vector、ArrayList和LinkedList。有關這些List類的性能差別是一個經常被問及的問題。在這篇文章中,我要探討的就是LinkedList和Vector/ArrayList之間的性能差異。為全面分析這些類之間的性能差異,我們必須知道它們的實現方法。因此,接下來我首先從性能的角度出發,簡要介紹這些類的實現特點。一、Vector和ArrayList的實現
Vector和ArrayList都帶有一個底層的Object[]數組,這個Object[]數組用來保存元素。通過索引訪問元素時,只需簡單地通過索引訪問內部數組的元素:
public Object get(int index)
{ //首先檢查index是否合法...此處不顯示這部分代碼 return
elementData[index]; } 內部數組可以大於Vector/ArrayList對象擁有元素的數量,兩者的差值作為剩餘空間,以便實現快速添加新元素。有了剩餘空間,添加元素變得非常簡單,只需把新的元素保存到內部數組中的一個空餘的位置,然後為新的空餘位置增加索引值:
public boolean add(Object o)
{ ensureCapacity(size + 1); //稍後介紹 elementData[size++] = o; return true;
//List.add(Object) 的返回值 }
把元素插入集合中任意指定的位置(而不是集合的末尾)略微復雜一點:插入點之上的所有數組元素都必須向前移動一個位置,然後才能進行賦值:
public void add(int index, Object element) {
//首先檢查index是否合法...此處不顯示這部分代碼
ensureCapacity(size+1);
System.array(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
剩餘空間被用光時,如果需要加入更多的元素,Vector/ArrayList對象必須用一個更大的新數組替換其內部Object[]數組,把所有的數組元素復制到新的數組。根據SDK版本的不同,新的數組要比原來的大50%或者100%(下面顯示的代碼把數組擴大100%):
public void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = Math.max(oldCapacity * 2, minCapacity);
elementData = new Object[newCapacity];
System.array(oldData, 0, elementData, 0, size);
}
}
Vector類和ArrayList類的主要不同之處在於同步。除了兩個只用於串列化的方法,沒有一個ArrayList的方法具有同步執行的能力;相反,Vector的大多數方法具有同步能力,或直接或間接。因此,Vector是線程安全的,但ArrayList不是。這使得ArrayList要比Vector快速。對於一些最新的JVM,兩個類在速度上的差異可以忽略不計:嚴格地說,對於這些JVM,這兩個類在速度上的差異小於比較這些類性能的測試所顯示的時間差異。通過索引訪問和更新元素時,Vector和ArrayList的實現有著卓越的性能,因為不存在除范圍檢查之外的其他開銷。除非內部數組空間耗盡必須進行擴展,否則,向列表的末尾添加元素或者從列表的末尾刪除元素時,都同樣有著優秀的性能。插入元素和刪除元素總是要進行數組復制(當數組先必須進行擴展時,需要兩次復制)。被復制元素的數量和[size-index]成比例,即和插入/刪除點到集合中最後索引位置之間的距離成比例。對於插入操作,把元素插入到集合最前面(索引0)時性能最差,插入到集合最後面時(最後一個現有元素之後)時性能最好。隨著集合規模的增大,數組復制的開銷也迅速增加,因為每次插入操作必須復制的元素數量增加了。二、LinkedList的實現
LinkedList通過一個雙向鏈接的節點列表實現。要通過索引訪問元素,你必須查找所有節點,直至找到目標節點:
public Object get(intindex) {
//首先檢查index是否合法...此處不顯示這部分代碼
Entry e = header; //開始節點
//向前或者向後查找,具體由哪一個方向距離較
//近決定
if (index < size/2) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
把元素插入列表很簡單:找到指定索引的節點,然後緊靠該節點之前插入一個新節點:
public void add(int index, Object element) {
//首先檢查index是否合法...此處不顯示這部分代碼
Entry e = header; //starting node
//向前或者向後查找,具體由哪一個方向距離較
//近決定
if (index < size/2) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
Entry newEntry = new Entry(element, e, e.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
}
線程安全的LinkedList和其他集合
如果要從Java SDK得到一個線程安全的LinkedList,你可以利用一個同步封裝器從Collections.synchronizedList(List)得到一個。然而,使用同步封裝器相當於加入了一個間接層,它會帶來昂貴的性能代價。當封裝器把調用傳遞給被封裝的方法時,每一個方法都需要增加一次額外的方法調用,經過同步封裝器封裝的方法會比未經封裝的方法慢二到三倍。對於象搜索之類的復雜操作,這種間接調用所帶來的開銷不是很突出;但對於比較簡單的方法,比如訪問功能或者更新功能,這種開銷可能對性能造成嚴重的影響。這意味著,和Vector相比,經過同步封裝的LinkedList在性能上處於顯著的劣勢,因為Vector不需要為了線程安全而進行任何額外的間接調用。如果你想要有一個線程安全的LinkedList,你可以復制LinkedList類並讓幾個必要的方法同步,這樣你可以得到一個速度更快的實現。對於所有其它集合類,這一點都同樣有效:只有List和Map具有高效的線程安全實現(分別是Vector和Hashtable類)。有趣的是,這兩個高效的線程安全類的存在只是為了向後兼容,而不是出於性能上的考慮。對於通過索引訪問和更新元素,LinkedList實現的性能開銷略大一點,因為訪問任意一個索引都要求跨越多個節點。插入元素時除了有跨越多個節點的性能開銷之外,還要有另外一個開銷,即創建節點對象的開銷。在優勢方面,LinkedList實現的插入和刪除操作沒有其他開銷,因此,插入-刪除開銷幾乎完全依賴於插入-刪除點離集合末尾的遠近。
ArrayList和Vector通常比LinkedList和同步封裝之後的LinkedList有著更好的性能。即使在你認為LinkedList可能提供更高性能的情況下,你也可以通過修改元素加入的方式從ArrayList爭取更好的性能,例如翻轉集合元素的次序。有些情況下LinkedList會有更好的性能,例如,當大量元素需要同時加入到大型集合的開頭和末尾時。但一般而言,我建議你優先使用ArrayList/Vector類,只有當它們存在明顯的性能問題而LinkedList能夠改進性能時,才使用LinkedList。