參考:https://www.cnblogs.com/zhouyuqin/p/5168573.html
Java集合總結
Java集合是每個Java程序員在日常開發(fā)中都會使用到,而且有時候使用得好的話乐设,能事半功倍驹愚。細數Java集合,其實比較常見的就是List裤纹、Set、Map和Queue案狠,在這四者之中服傍,除了Map之外钱雷,其他三個接口都繼承于Collection。
在這里吹零,首先我們要明確的是罩抗,List、Set灿椅、Map和Queue其實只是以接口的形式存在著的套蒂,所以在日常的程序開發(fā)中,請不要出現說想要直接初始化它們的想法和做法茫蛹,雖然筆者也曾經犯過這樣子的錯誤操刀。
繼承與Collection接口的–List接口
List接口本身的特點
List接口在Java的集合類中充當的是一個元素有序、元素可重復的集合角色婴洼。List繼承于Collection集合骨坑,故其擁有了Collection集合的全部方法,同時柬采,List集合也擁有屬于自己的方法:用來實現根據元素索引來操作集合元素的作用欢唾。通過List集合的源碼(JDK1.7)我們簡單地看看List集合包含的方法:
package java.util;
public interface List extends Collection {
int size(); //集合元素的數量
boolean contains(Object o); //是否包含某變量,包含返回ture
Iterator<E> iterator();
Object[] toArray(); //將集合轉化為一個數組粉捻,所有的集合元素變成相應的數組元素
<T> T[] toArray(T[] a); //將集合轉化為一個類型T數組
boolean add(E e); //增加元素礁遣,成功返回true
boolean remove(Object o); //移除元素,成功返回true
boolean containsAll(Collection<?> c); //是否包含集合c中的全部元素肩刃,若是返回true
boolean addAll(Collection<? extends E> c); //添加整個集合c中全部元素祟霍,
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c); //移除該List集合中包含的c中的全部元素
boolean retainAll(Collection<?> c); //是否包含c集合中的元素,包含返回ture
void clear(); //清空集合
boolean equals(Object o);
int hashCode();
E get(int index); //根據index取元素值
E set(int index, E element); //根據index把List該元素重新復制element
void add(int index, E element); //根據index添加新元素element
E remove(int index);
int indexOf(Object o); //返回對象o在List集合中第一次出現的位置索引
int lastIndexOf(Object o); //返回對象o在List集合中最后一次出現的位置索引
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex); //截斷集合
}
常見的繼承List接口的實用類
ArrayList
ArrayList是基于數組實現的List類盈包,故其封裝了一個動態(tài)的沸呐、允許再分配的Object[]數組,ArrayList用initialCapacity參數來設置該數組的長度续语,當長度超過預設值后垂谢,ArrayList會動態(tài)增加。
ArrayList類是線程不安全的疮茄,如果要保證該集合的同步性滥朱,必須在程序中手動保證。
值得注意的是:雖說與以鏈表形式建立的LinkedList相比力试,ArrayList()的插入和修改速度較慢徙邻,但那個也是建立在數據量較大的情況下的,在數據量較小的情況下畸裳,ArrayList()不一定比LinkedList()方法要慢缰犁。另外,ArrayList在末尾插入和刪除數據的話,速度反而比LinkedList要快
LinkedList
LinkedList(): 在實現中采用鏈表數據結構帅容。插入和刪除速度快颇象,訪問速度慢。
因為除了繼承List接口外并徘,LinkedList接口也繼承了Deque接口遣钳,故也可以當作“棧”和隊列(雙向隊列)來使用麦乞。因此LinkList接口也會多出一些Deque接口方面的方法蕴茴,如offer()(將元素接到隊列的尾部)、push()或offerFirst()(將元素加入棧的頂部)姐直、peek()或peekFirst()(訪問但是不刪除棧頂元素)倦淀、pop()或者pollLast()(將棧頂元素彈出棧)等方法。
Vector
Vector與ArrayList十分地相像声畏,都是基于數組實現的List類撞叽,其也是封裝了一個動態(tài)分配的Object[]數組,也可以使用initialCapacity參數來設置該數組的長度砰识。
Vector是線程安全的能扒,但是也因此Vector的性能很差佣渴。
Stack
Stack是繼承與Vector的子類辫狼,它主要用來模擬”棧“辛润,因此也具備了peek()膨处、pop()、push()等主要用于棧操作的方法砂竖。
由于Stack是一個比較古老的Java集合類真椿,它同樣是線程安全的,但也因此暴露出了性能較差的缺點乎澄,如果程序中要使用棧這樣的數據結構的話突硝,可以試一試ArrayDeque,該類也是List的實現類置济,但和LinkedList一樣也繼承了Deque接口解恰。
實用類對比
使用List集合有以下建議:
1、遍歷集合元素浙于。ArrayList和Vector使用get()方法來獲取遍歷元素护盈,LinkedList應該采用迭代器來遍歷集合元素。
2羞酗、插入和刪除腐宋。當這類操作較多的時候,優(yōu)先考慮使用LinkedList。
3胸竞、多線程欺嗤。當需要使用到多線程的ArrayList時,可以使用Collections將該集合類包裝成線程安全的集合卫枝。
繼承與Collection接口的–Set接口
Set接口本身的特點
Set代表的是無序的剂府、不可重復的集合。因此在Set集合中加入數據元素時剃盾,Set集合通常不用記住元素的添加順序腺占。不可重復則是說當將兩個相同的元素加入到一個Set集合中,則添加操作失敗痒谴,add()方法返回false衰伯,且新元素不會被添加。
public interface Set extends Collection {
int size(); //集合元素的數量
boolean isEmpty(); //判斷集合是否為空
boolean contains(Object o); //是否包含某變量积蔚,包含返回ture
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c); //是否包含c集合中的元素意鲸,包含返回ture
boolean addAll(Collection<? extends E> c); //添加包含c集合中所有的元素,包含返回ture
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();
}
常見的繼承Set接口的實用類
HashSet
HashSet按照Hash算法來存儲集合中的元素尽爆,因此具有良好的存取和查找功能怎顾。
HashSet有三個特點:與TreeSet不同,HashSet是無序的漱贱;不是線程同步槐雾;集合元素可以是null值。
HashSet集合的存儲過程:當向HashSet集合中存入一個元素時幅狮,HashSet會調用該對象的hashCode()方法來得到該對象的hashCode值募强,然后根據該值決定該對象在HashSet中的存儲位置。如果有兩個元素通過equals()方法返回true崇摄,但他們的hashCode()方法返回值不相等擎值,HashSet也會將其存儲在不同的位置。也就是說:HashSet的添加元素判斷標準是:兩個對象通過equals()方法比較相等逐抑,并且兩個對象的hashCode()方法返回值也相等鸠儿。
LinkedHashSet
LinkedHashSet是繼承于HashSet的子類。
但是與父類不同的是厕氨,LinkedHashSet用以鏈表的形式來維護元素的次序进每,也就是說:LinkedHashSet是有序的。遍歷該集合時輸出順序為添加順序腐巢。
TreeSet
TreeSet是SortedSet接口的實現類品追,所以TreeSet可以確保集合元素處于排序狀態(tài)。TreeSet使用紅黑樹來維護集合元素的次序冯丙。如果實現comparator()方法肉瓦,可以實現定制排序遭京。如果采用自然排序,則返回null泞莉。
TreeSet集合的特有方法:first()哪雕、last()、lower(Object e)(返回指定元素之前的元素)鲫趁、higher(Object e)(返回指定元素之后的元素)等等斯嚎。
下面我們說一說TreeSet的定制排序和自然排序:
1、 定制排序
通過Comparator接口的幫助挨厚,實現降序排序堡僻。
2、 自然排序
TreeSet通過CompareTo(Object obj)比較元素之間的大小關系疫剃,將集合元素按升序排列钉疫。實現元素必須實現Comparable元素,而且在比較的時候如果出現不同類型時要轉換類型后比較巢价。
EnumSet
EnumSet是專門為枚舉類設計的集合類牲阁,EnumSet中的所有元素都必須是指定枚舉類型的枚舉值,該枚舉類型在創(chuàng)建EnumSet時顯式或隱式地指定壤躲。
EnumSet在內部以位向量的形式存儲城菊,十分緊湊、高效碉克,因此EnumSet對象占用內存很小凌唬,且運行效率很高。但是該集合元素中不允許加入null元素棉胀。
實用類對比
繼承與Collection接口的–Queue接口
Queue接口本身的特點
Queue用來模擬隊列這種數據結構法瑟,故其擁有add()、element()唁奢、offer()、peek()窝剖、poll()麻掸、remove()等方法。
package java.util;
public interface Queue extends Collection {
boolean add(E e); //在隊尾增加元素e
boolean offer(E e); //在隊尾增加元素e
E remove(); //獲取隊列頭部的元素赐纱,并移除該元素
E poll(); //獲取隊列頭部的元素脊奋,并移除該元素
E element(); //獲取隊列頭部的元素,但不移除該元素
E peek(); //獲取隊列頭部的元素疙描,但不移除該元素
}
常見的繼承Queue接口的實用類
PriorityQueue
PriorityQueue是Queue的標準隊列實現類诚隙。PriorityQueue不是按照加入隊列的順序進行排列的,而是根據隊列大小進行重新排序的(升序)起胰,這一點要特別注意的久又。
PriorityQueue中不允許插入null元素,它也有兩種排序方式:自然排序(實現Comparable接口,且為同一個類比較)和定制排序(建立對象時傳入一個Comparator對象)地消。這個部分和TreeSet的要求基本一致炉峰。
Deque–ArrayDeque
首先要說明的是:Deque是Queue的子接口,代表的是雙向鏈表脉执,故該接口中也定義了一些方法來從兩端來操作隊列的數據疼阔。
ArrayDeque:是一個基于數組實現的雙端隊列,它與ArratList的實現體制很相像半夷,都會采用了動態(tài)可再分配的數組來存儲集合元素婆廊。但是其在用途上主要是被當作”棧“來使用巫橄。
Deque–LinkedList
LinkedList在上述已表述過否彩。與ArrayDeque不同的是,LinkedList是使用鏈表實現的嗦随。
特例獨立的–Map接口
Map接口本身的特點
Map與上述三個接口不同的是列荔,該接口無法繼承于Collection接口,主要原因還是因為Map是用來存儲具有映射關系的數據枚尼,所以Map中保存著兩組值贴浙。一組值用來保存Map中的Key,另外一組用來保存Map里的value署恍。值得注意的是:Map中的key不能重復崎溃。判斷標準是同一個Map對象的任何兩個key通過equals方法比較總是返回false。
package java.util;
public interface Map {
int size();
boolean isEmpty();
boolean containsKey(Object key); //是否包含key值盯质,如果是返回true
boolean containsValue(Object value); //是否包含value值袁串,如果是返回true
V get(Object key); //根據key值獲取相應的value值
V remove(Object key); //根據key值從集合中移除相應的value值
void putAll(Map<? extends K, ? extends V> m); //將指定的m中的key-value復制到該集合中
void clear();
Set<K> keySet(); //返回該Map中所有key組成Set集合
Collection<V> values(); //返回該Map中所有的value組成的Collection
Set<Map.Entry<K, V>> entrySet(); //返回Map中包含的key-value對所組成的Set組合,每個集合元素都是Map.Entry對象呼巷。
interface Entry<K,V> {
K getKey(); //返回該Entry里面包含的key值
V getValue(); //返回該Entry里面包含的value值
V setValue(V value); //設置原本的value值并返回該值
boolean equals(Object o);
int hashCode();
}
boolean equals(Object o);
int hashCode();
}
Map與Set相似度極高囱修,將Map中的key和value分離開來看。key組是使用set集合方法來存儲的王悍。不僅如此破镰,在子類的實現方面,兩者也有很多的相似压储,所以你也會發(fā)現兩者子類的命名很相像鲜漩。
常見的繼承Map接口的實用類
HashMap
HashMap是線程不安全的實現,且HashMap中可以使用null作為key或者value集惋。
LinkedHashMap
LinkedHashMap使用一個雙向鏈表來維護key-value對的次序孕似,其也是一個有序的Map集合,順序與key-value對的插入順序保持一致刮刑。
TreeMap
TreeMap是一個紅黑樹的結構喉祭,每個key-value作為紅黑樹的一個節(jié)點养渴。TreeMap也會對key進行排序,也分為自然排序和定制排序兩種臂拓。
EnumMap
EnumMap是一個與枚舉類一起使用的Map實現厚脉。
HashTable
HashTable是一個比較古老的Map實現類,它是一個線程安全的Map實現胶惰,且不允許使用null作為key和value傻工。由于該類是比較久遠的類,其性能較低孵滞,所以現在用的也比較少中捆。
HashTable判斷value相等的標準是:value與另外一個對象通過equals()方法返回true即可。
實用類對比
一般的應用場景坊饶,使用HashMap已經夠用了泄伪。它非常適合于快速查詢。但是如果程序需要一個排序的Map集合匿级,可以考慮使用TreeMap蟋滴。
操作集合的工具類:Collections
Java提供了一個操作Set、List和Map等集合的工具類:Collections痘绎,該類提供了大量的方法對集合元素進行排序津函、查詢和修改等操作,還提供了將集合對象設置為不可變孤页、對集合對象實現同步控制尔苦。
排序:reverse()(反轉集合元素順序)、shuffle()(隨機排列)行施、sort()允坚、swap()等方法。
查找和替換:binarySearch(list,obj)(二分查找指定List集合元素obj的索引)蛾号、max()稠项、min()、fill()须教、frequency()(返回指定集合元素的出現次數)皿渗、replaceAll()等方法。
同步控制:Collections提供了多個synchronizedXxx()方法轻腺,該方法可以將指定的集合包裝成線程同步的集合,進而解決了多線程并發(fā)訪問集合時的線程安全問題划乖。
設置不可變集合:Collections提供三個方法來返回一個不可變的集合:emptyXxx()(返回一個空的贬养、不可變的集合對象)、singletonXxx()琴庵、unmodifiableXxx()方法误算。