java基礎2 容器類詳解
容器類繼承框架
java.util.Collection
是一個集合接口。它提供了對集合對象進行基本操作的通用接口方法。Collection接口在Java 類庫中有很多具體的實現。Collection接口的意義是爲各種具體的集合提供了最大化的統一操作方式。
java.util.Collections
是一個包裝類。它包含有各種有關集合操作的靜態多態方法。此類不能實例化,就像一個工具類,服務於Java的Collection框架。
Java容器類庫定義了兩個不同概念的容器,Collection 和 Map
- Collection:獨立元素的序列,這些元素都服從一條或多條規則。其中List必須按照插入的順序保存元素、Set不能有重複的元素
- Map:一組成對的值鍵對對象,允許用鍵來查找值。ArrayList允許我們用索引來查找值,它是將索引和對象聯繫在一起。而Map允許我們使用一個對象來查找某個對象,它也被稱爲關聯數組。或者叫做字典
List(列表:有序性)
List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。實現List接口的常用類有LinkedList,ArrayList,Vector和Stack。
List(列表) 有序,可重複
LinkedList類
LinkedList實現了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在 LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque);LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:List list = Collections.synchronizedList(new LinkedList(…));
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。size,isEmpty,get,set方法運行時間爲常數。但是add方法開銷爲分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間爲線性。每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨着不斷添加新元素而自動增加,但是增長算法並 沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。一般情況下使用這兩個就可以了,因爲非同步,所以效率比較高。對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
Vector類
Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的 Iterator是同一接口,但是,因爲Vector是同步的,當一個 Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例 如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出 ConcurrentModificationException,因此必須捕獲該 異常。
Stack 類
Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方 法,還有 peek方法得到棧頂的元素,empty方法測試堆棧是否爲空,search方法檢測一個元素在堆棧中的位置。Stack剛創建後是空棧。
對比
ArrayList
優點: 底層數據結構是數組,查詢快,。效率高
缺點: 線程不安全,增刪相對LinkedList慢
Vector
優點: 底層數據結構是數組,查詢快,增刪慢。
缺點: 線程安全,效率低
LinkedList
優點: 底層數據結構是鏈表,增刪快。效率高
缺點: 線程不安全,查詢相對ArrayList慢
Set(集合,唯一性)
Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。 Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。
HashSet類
- 它不允許出現重複元素
- 不保證和政集合中元素的順序
- 允許包含值爲null的元素,但最多只能有一個null元素。
TreeSet類
TreeSet描述的是Set的一種變體——可以實現排序等功能的集合,它在講對象元素添加到集合中時會自動按照某種比較規則將其插入到有序的對象序列中
對比
HashSet
底層數據結構是哈希表。(無序,唯一)
如何來保證元素唯一性?
1.依賴兩個方法:hashCode()和equals()
LinkedHashSet
底層數據結構是鏈表和哈希表。(FIFO插入有序,唯一)
1.由鏈表保證元素有序
2.由哈希表保證元素唯一
TreeSet
底層數據結構是紅黑樹。(唯一,有序)
1. 如何保證元素排序的呢?
自然排序
比較器排序
2.如何保證元素唯一性的呢?
根據比較的返回值是否是0來決定
### hashSet,linkhashset,TreeSet
- hashSet 效率最高,無序
- linkhashset效率略低,有序
- TreeSet效率最低,可以排序
Map(映射,鍵值對)
Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個 value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
HashMap類
維護一個數組鏈表,HashMap是非同步的,hashtable是同步的,
構造方法
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public HashMap(int initialCapacity, float loadFactor){};
initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作
Hashtable類
hashmap key可以null,value 可以null,hashtable均不能爲null
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那麼該key可以被GC回收。
Map接口有三個比較重要的實現類,分別是HashMap、TreeMap和HashTable。
TreeMap是有序的,HashMap和HashTable是無序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。這是兩者最主要的區別
擴展
hashmap 和hashtable;StringBuilder和StringBuffer的區別
- hashtable線程安全,效率低,hashmap線程不安全,效率高
- StringBuffer線程安全,效率低,StringBuilder線程不安全,效率高
集合的使用
List 去重
通過HashSet踢除重複元素
public static List removeDuplicate(List list) {
HashSet h = new HashSet(list);
list.clear();
list.addAll(h);
return list;
}
刪除ArrayList中重複元素,保持順序
// 刪除ArrayList中重複元素,保持順序
public static void removeDuplicateWithOrder(List list) {
Set set = new HashSet();
List newList = new ArrayList();
for (Iterator iter = list.iterator(); iter.hasNext();) {
Object element = iter.next();
if (set.add(element))
newList.add(element);
}
list.clear();
list.addAll(newList);
System.out.println( " remove duplicate " + list);
}
把list裏的對象遍歷一遍,用list.contain(),如果不存在就放入到另外一個list集合中
public static List removeDuplicate(List list){
List listTemp = new ArrayList();
for(int i=0;i<list.size();i++){
if(!listTemp.contains(list.get(i))){
listTemp.add(list.get(i));
}
}
return listTemp;
}
HashMap的put與putIfAbsent區別
- put在放入數據時,如果放入數據的key已經存在與Map中,最後放入的數據會覆蓋之前存在的數據,
- putIfAbsent在放入數據時,如果存在重複的key,那麼putIfAbsent不會放入值。
java foreach語法以及迭代器實現
https://blog.csdn.net/w1764662543/article/details/92795338
HashMap和HashTable配置
HashMap和HashTable可以通過配置,其構造方法見
構造方法
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public HashMap(int initialCapacity, float ){};
- initialCapacity:初始容量,、哈希表創建時的容量桶的容量
- loadFactor:加載因子,哈希表在其容量增加之前可以達到多滿的一個尺度。
- hash衝突:數組的長度是5。這時有一個數據是6。那麼如何把這個6存放到長度只有5的數組中呢。按照取模法,計算
6%5,結果是1,那麼就把6放到數組下標是1的位置。那麼,7
就應該放到2這個位置。到此位置,哈斯衝突還沒有出現。
這時,有個數據是11,按照取模法,11%5=1,也等於1。那麼
原來數組下標是1的地方已經有數了,是6。這時又計算出1這個
位置,那麼數組1這個位置,就必須儲存兩個數了(hash表中鏈表能存儲多個數據)。這時,就叫
哈希衝突。 - loadFactor就是爲了減少hash衝突配置的,