1. 程式人生 > >java基礎——2——集合概述

java基礎——2——集合概述

Java的集合類主要由兩個介面派生而來:Collection和Map。Collection和Map是Java集合框架的根介面,這兩個介面又包含了一些子介面或實現類。這裡寫圖片描述

這裡寫圖片描述
Set集合
Set集合是Collection集合的子類,與Collection基本上完全一樣,它沒有提供額外的方法,只是在行為上略有不同。
Set集合不允許包含相同的元素,如果把兩個相同的元素加入到同一個Set集合中去,則新增操作失敗,add方法返回false,且新元素不會被加入。
Set判斷兩個物件相同不是使用==運算子,而是使用equals方法。也就是說,只要兩個物件equals方法比較返回true,Set就不會接受這兩個物件;反之,則可以。
HashSet類


HashSet是Set介面的典型實現,大多數時候使用Set集合時就是使用這個實現類。HashSet按Hash演算法來儲存集合中的元素,因此具有很好的存取和查詢效能。
HashSet具有以下特點:
不能保證元素的排列順序,排列順序可能與新增順序不同。
HashSet不是同步的,如果多個執行緒同時訪問一個HashSet時,假設有一個或多個執行緒同時修改了HashSet集合時,則必須通過程式碼塊來保證其同步。
集合元素可以是null。
當向HashSet集合中存入一個元素時,HashSet會呼叫該物件的hashCode()方法來得到該物件的值,然後根據該HashCode()值決定該物件在HashSet中的儲存位置。如果兩個元素通過equals()方法比較返回true,而他們的hashCode()方法返回值不同,HashSet會將他們儲存在不同的位置,依然新增成功。這就與Set集合的規則有些出入了。
注意:如果通過equals方法比較返回true,同時根據hashCode()方法獲取的返回值也相同,則只能儲存一個物件。
當把一個物件放入到HashSet中時,如果重寫了這個物件的equals方法,那麼也必須重寫這個物件的hashCode方法。其規則就是如果equals方法返回true,那麼這兩個物件的hashCode的值也應該相同。
如果兩個物件通過equals方法比較返回false,而hashCode值返回一樣,這就有點違背了HashSet的設計規則,本來通過Hash演算法我們可以計算物件的儲存位置,現在卻成了在同一個位置上儲存了兩個物件。從而減低了HashSet快速查詢物件的功能。
LinkedHashSet類

LinkedHashSet是HashSet的子類,LinkedHashSet同樣是根據元素的hashCode值來決定元素的儲存位置,但與HashSet不同的是,LinkedHashSet在儲存物件時同時使用連結串列維護了元素的次序,即:當遍歷LinkedHashSet集合裡的元素時,LinkedHashSet將會按照元素的新增順序來訪問集合裡的元素。
TreeSet是SortedSet介面的實現類,TreeSet可以確保集合元素處於排序狀態。與HashSet相比,TreeSet還提供了額外方法:
Comparator comparator():如果TreeSet採用了定製排序,則該方法返回定製排序所使用的Comparator,如果TreeSet採用了自然排序,則返回null。
Object first():返回集合中的第一個元素。
Object last():返回集合中的最後一個元素。
Object lower(Object obj):返回集合中位於指定元素之前的元素。
Object higher(Object obj):返回集合中位於指定元素之後的元素。
SortedSet subSet(fromElement,toElement):返回此Set的子集合,範圍從fromElement(包含)到toElement(不包含)。
SortedSet headSet(toElement):返回Set的子集,由小於toElement的元素組成。
SortedSet tailSet(fromElement):返回Set的子集,由大於或等於fromElement的元素組成。
HashSet集合採用hash演算法來決定元素的儲存位置,TreeSet採用紅黑樹的資料結構來儲存集合元素。TreeSet支援兩種排序方法:自然排序和定製排序。
自然排序

TreeSet會呼叫集合元素的compareTo(Object obj):方法來比較元素之間的大小關係,然後將集合元素按升序排列,這種方式就是自然排序。
Java中提供了一個Comparable介面,此介面中定義了一個方法compareTo(Object obj),該方法返回一個整數值,實現了該介面的類的物件就可以比較大小。由於在向TreeSet集合中存放資料時,TreeSet會呼叫該元素物件的compareTo方法,因此往TreeSet集合中存放是元素物件必須實現了該方法。
大部分類在實現compareTo方法時,都需要將被比較物件obj強制轉換成相同型別,因為只有相同型別的例項才能比較大小。因此TreeSet集合中存放的元素必須是同一型別的例項。
否則將會丟擲ClassCastException(強制型別轉換異常)
定製排序
TreeSet的自然排序是根據集合元素的大小,TreeSet將它們以升序排序。如果實現定製排序,比如降序,需要通過Comparator介面來實現。在建立TreeSet例項的時候,不在使用TreeSet預設的比較,通過Comparator介面實現自己的比較器例項,將比較器的例項作為引數通過TreeSet的構造器傳遞給集合,那麼在往集合元素中存放資料的時候就會按照我們的指定順序進行排序。實現Comparator介面的int compare(T t1,T t2)方法,此方法在往集合元素中新增元素物件時被呼叫,該方法返回一個int型別值,返回正整數,表示t1大於t2,返回負整數,表示t1小於t2,返回0表示,t1等於t2.
List集合
List集合代表一個存放元素物件為有序、可重複的集合,集合中每個元素都有其對應的順序索引。List集合允許使用重複元素,可以通過索引來訪問指定位置的集合元素。List集合預設按元素的新增順序設定元素的索引。
List作為Collection介面的子介面,可以使用Collection接口裡的全部方法。由於List又是一個有序的集合,所以List集合中又增加了一些根據索引來操作集合元素的方法。
void add(int index,Object element):將元素element插入到List集合的index處。如果當前索引位置有元素物件,則將此元素物件及後面所有元素物件都向後移動一個索引位置。
Boolean addAll(int index,Collection c):將集合c所包含的所有元素都插入到List集合中的index索引位置。
Object get(int index):返回集合index索引位置的元素。
Int indexOf(Object o):返回物件o在List集合中第一次出現的位置索引。
Int lastIndexOf(Object o):返回物件o在List集合中最後一次出現的位置索引。
Object remove(int index):刪除index索引位置的元素,並將此物件返回。同時此元素後面的所有元素索引向前前進一位。
Object set(int index,Object element):將index索引處的元素替換成element物件,並將被替換的元素返回。
List subList(int fromIndex,int toIndex):返回從元素索引fromIndex到索引toIndex處所有集合元素組成的子集合。
List作為Collection介面的子介面,可以使用Collection接口裡的全部方法。由於List又是一個有序的集合,所以List集合中又增加了一些根據索引來操作集合元素的方法。
void add(int index,Object element):將元素element插入到List集合的index處。如果當前索引位置有元素物件,則將此元素物件及後面所有元素物件都向後移動一個索引位置。
Boolean addAll(int index,Collection c):將集合c所包含的所有元素都插入到List集合中的index索引位置。
Object get(int index):返回集合index索引位置的元素。
Int indexOf(Object o):返回物件o在List集合中第一次出現的位置索引。
Int lastIndexOf(Object o):返回物件o在List集合中最後一次出現的位置索引。
Object remove(int index):刪除index索引位置的元素,並將此物件返回。同時此元素後面的所有元素索引向前前進一位。
Object set(int index,Object element):將index索引處的元素替換成element物件,並將被替換的元素返回。
List subList(int fromIndex,int toIndex):返回從元素索引fromIndex到索引toIndex處所有集合元素組成的子集合。
ListIterator介面:List提供了一個listIterator()方法,該方法返回一個ListIterator物件,ListIterator介面繼承了Iterator介面,還提供了專門操作List的方法。方法如下:
Boolean hasPrevious():返回該迭代器關聯的集合是否含有上一個元素。
Object previous():返回迭代器的上一個元素。
void add():在指定位置插入一個元素。
ListIterator與普通的Iterator進行對比,ListIterator增加向前迭代的功能,而且還通過add方法向List集合中新增元素。
ArrayList和Vector是List介面的典型實現,都是基於陣列實現的List類。ArrayList和Vector都封裝了一個動態的允許再分配的Object[]陣列。
ArrayList和Vector的用法幾乎完全一樣,但是Vector與ArrayList相比較而言是屬於古董級別,在JDK1.0時就已經存在。那時Java還沒有提供系統的集合框架,Vector中提供了很多方法名很長的方法。從JDK1.2以後,Java提出系統集合框架之後,將Vector改為實現List介面,作為List的實現類之一,從而導致了Vector中存在了一些功能重複的方法。
因此儘量少用Vector,因為能用Vector的地方就能用ArrayList來代替。除此之外,ArrayList與Vector的顯著區別是:ArrayList是執行緒不安全的,Vector是執行緒安全,所以Vector的效能要比ArrayList要低一些。即使是為了保證List集合的執行緒安全,同樣不推薦使用Vector實現類,後面會介紹Collections工具類,它會是ArrayList變成執行緒安全的。
Queue集合
Queue用於模擬佇列資料結構,佇列是遵循“先進先出”,“後進後出”的儲存規範。第一個存放的元素物件存放在佇列隊首位置,後進入的元素插入到隊尾的位置,佇列不允許隨機訪問佇列中元素。
Queue介面定義的方法:
void add(Object obj):將指定元素加入此佇列的尾部。
Object element():獲取佇列頭部的元素,但不刪除該元素。
boolean offer(Object obj):將指定元素加入此佇列的尾部,當使用有容量限制的佇列時,此方法比add()方法更好。
Object peek():獲取佇列頭部的元素,但不刪除該元素。如果此佇列為空,返回null。
Object poll():獲取佇列頭部的元素,並刪除該元素,如果此佇列為空,返回Null。
Object remove():獲取佇列頭部的元素,並刪除該元素。
PriorityQueue是一個比較標準的Queue實現類,而不是絕對標準的佇列實現,是因為PriorityQueue儲存佇列元素的順序並不是按照加入佇列的順序進行儲存。而是按照佇列元素的大小進行重新一次排序。因此使用peek()或者poll()方法獲取元素佇列位置時,並不一定就是首先存入的元素物件,而是佇列中最小的元素。
注意:PriorityQueue不允許插入null值,它需要對佇列元素進行排序,PriorityQueue的元素排序分兩種情況,自然排序和定製排序,參照TreeSet。
Deque介面是Queue介面的子介面,它代表一個雙端佇列,Deque接口裡定義了一些雙端佇列的方法,這些方法允許從兩端來操作佇列元素。
void addFirst(Object obj):將指定元素插入到該佇列的首部。
void addlast(Object obj):將指定元素插入到該佇列的尾部。
Iterator desceningIterator():返回該雙端佇列對應的迭代器,該迭代器將以逆向順序來迭代佇列中的元素。
Object getFirst():獲取雙端佇列的第一個元素。
Object getLast():獲取雙端佇列的最後一個元素。
Boolean offerFirst(Object obj):將指定元素插入到雙端佇列的開頭。
Boolean offerLast(Object obj):將指定元素插入到雙端佇列的末尾。
Object peekFrist():獲取但不刪除雙端佇列的第一個元素。
Object peekLast():獲取但不刪除雙端佇列的最後一個元素。
Object pollFrist():獲取並刪除雙端佇列的第一個元素。
Object pollLast():獲取並刪除雙端佇列的最後一個元素。
Object pop():獲取並刪除該雙端佇列的第一個元素。
void push(Object obj):將一個元素插入到該雙端佇列的隊首位置,相當於addFrist()
Object removeFirst():獲取並刪除該雙端佇列的第一個元素。
Object removeLast():獲取並刪除該雙端佇列的最後一個元素。
LinkedList類是List介面的實現類,因此可根據索引來隨機訪問集合中元素。LinkedList還實現了Deque介面,因此可被當做雙端佇列來使用,同樣也可以被當做“棧”來使用。
LinkedList與ArrayList、ArrayDeque的實現機制不同,ArrayList和ArrayDeque內部以陣列的形式來儲存集合中元素,因此隨機訪問集合元素時有較好的效能。而LinkedList內部以連結串列的形式來儲存集合中的元素,因此隨機訪問集合元素時效能不如ArrayList和ArrayDeque。而插入、刪除元素時效能非常出色,只需要改變指標所指向的地址即可。
Properties類是Hashtable類的子類,該物件在處理屬性檔案時非常方便。Properties類可以把Map物件和屬性檔案關聯起來,從而可以把Map物件中的key-value對寫入到屬性檔案中,也可以把屬性檔案中的“屬性名=屬性值”載入到Map物件中。由於屬性檔案裡的屬性名、屬性值只能是字串型別,所有Properties裡的key、value都是字串型別。該類的常用方法如下
String getProperty(String key):獲取Properties中指定屬性名對應的屬性值。
String getProperty(String key,String defaultValue):方法過載,獲取Properties中指定屬性名對應的屬性值,如果此屬性名不存在時,返回預設的defaultValue值。
Object setProperty(String key,String value):設定屬性值,類似於Map的put()方法。
void load(InputStream inStream):從屬性檔案中載入key-value對。
void store(OutputStream out,String comments):將Properties中的key-value對輸入到指定的屬性檔案中。
屬性檔案格式:在windows系統下屬性檔案常以.ini進行結尾,在Java中屬性檔案以.properties結尾
如同Set介面派生出SortedSet子介面,SortedSet介面有一個實現類TreeSet一樣,Map介面也有一個SortedMap介面,SortedMap介面也有一個實現類TreeMap。TreeMap就是一個紅黑樹資料結構,每個key-value對即作為紅黑樹的一個節點。TreeMap儲存key-value對時,需要根據key對節點進行排序。TreeMap保證所有的key-value對都處於有序的狀態。
TreeMap的兩種排序方式:
1、自然排序:TreeMap的所有key必須實現Comparable介面,而且所有的key應該是同一個類的物件,否則丟擲ClassCastException(型別轉換異常)。
2、定製排序:建立TreeMap物件時,傳入一個Comparator物件,該物件負責對TreeMap中的所有key進行排序。採用定製排序時不需要key實現Comparable介面。