成鵬致遠 | lcw.cnblog.com |2014-02-04
JAVA類集
1.認識類集
- 類集的作用
- 類集實際上就是一個動態的物件陣列,與一般的物件陣列不同,類集中的物件內容可以任意擴充
- 類集的特徵
- 這種框架是高效能的
- 框架必須允許不同型別的類集以相同的方式和排程互操作方式工作
- 類集必須是容易擴充套件和修改的
- 物件陣列中包含一組物件,但是物件陣列使用的時候存在一個長度的限制,那麼類集是專門解決這種限制的,使用類集可以方便的向陣列中增加任意多個資料
- 物件陣列的操作中基本上都要保證物件型別的一致性,對於類集而言本身其內部的元素也應該保持一致,不管是何種型別的資料,所有的操作方式都應該是一樣的
- 類集框架的主要介面
- 以上的介面必須全部掌握,並且掌握各個介面的主要特點
- 所有的類集操作都存放在 java.util包中
- Collection介面使用注意
- 在一般的開發中,往往很少去直接使用 Collection介面進行開發,而基本上都是使用其子介面
- 子介面主要有:List、Set、Queue、SortedSet
- 使用子介面,可以更加清楚的表示出操作的型別(比如是否允許重複)
- List介面:可以存放重複的內容
- Set介面:不能存放重複的內容,所有的重複內容是靠 hashCode()和 equals()兩個方法區分的
- Queue:佇列介面
- SortedSet介面:可以對集合中的資料進行排序
- 小結
- 掌握類集就是一個動態的物件陣列
- 主要的操作介面
2.List介面
- List介面中可以存放任意的資料,而且在 List介面中內容是允許重複的
- List介面的常用子類:ArrayList
- ArrayList是 List的子類,可以直接通過物件的多型性,為 List介面例項化
- 要想使用介面,則肯定要使用物件的多型性進行例項化的操作,那麼對於 List介面本身也是一樣的
- ArrayList中可以增加一個資料,也可以增加一組資料
- List中存在兩種刪除:根據物件內容、根據物件的編號
- 集合中的內容可以新增,可以刪除,那麼實際上最重要的就是輸出
- 在 List介面中提供了 get()方法,利用此方法就可以完成輸出,此輸出文壇是 List介面所獨有的,而其它介面是沒有的,尤其是 Collection中是沒有根據索引取出內容的操作
- 通過迴圈完成輸出,迴圈的次數由 size()方法取得
- 集合中還有以下的操作
- 判斷集合是否為空:boolean isEmpty()
- 擷取部分集合:List<E> subList(int fromIndex, int toIndex),List介面擴充
- 查詢指定物件是否存在:int indexOf(Object o),如果查詢則返回位置,否則返回 -1
- 查詢是否存在:boolean contains(Object o)
- 挽救的子類:Vector
- Vector算是一個元老級的類,在 JDK1.0的時候就存在此類,但到了 JDK1.2之後重點強調集合框架的概念,所以先後定義了很多新介面(如:List等),但是考慮到一大部分的人已經習慣了使用 Vector類,所以就讓 Vector類多實現了一個 List介面,這才將其保留下來
- 但是因為其是 List子類,所以 Vector類的使用與之前的並沒有太大的區別
- ArrayList與 Vector的區別
- 小結
- 掌握了以上的的操作方法,實際上 List介面的作用就明白了,而且之後的全部 操作中也基本上都是以這些方法為操作的標準,只是各個的特性不一樣,例如:List中允許有重複的元素
- ArrayList和 Vector的區別
3.LinkedList類
- LinkedList表示的是一個連結串列的操作類,此類定義如下:public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>,Queue<E>,Cloneable,Serializable
- Queue介面是 Collection的子介面
- LinkedList本身大量的擴充了 Queue介面和 List介面的操作,所以,在使用時最好直接使用 LinkedList類完成操作
- 常用操作
- 為連結串列的開頭和結尾增加資料
- 對於連結串列也可以找到其表頭,可以刪除表頭,也可以不刪除
- 此類實現了 Queue介面,可以按照佇列的方式進行 FIFO的操作
- 小結
- 實際上此集合中增加元素的操作都是一樣的,因為都是 Collection的子類
- 各個類有各個類自己的單獨的實現,只需要單獨使用即可
4.Set介面
- Set介面也是 Collection介面的子介面,但是與 Collection或 List介面不同的是,Set介面中不能加入重複的元素
- Set介面的定義:public interface Set<E> extends Collection<E>
- Set介面的主要方法與 Collection是一致的
- Set介面的例項無法像 List介面那樣進行雙向輸出
- Set介面的常用子類
- 雜湊在這:HashSet
- 有序存放:TreeSet
- Collection就不能進行雙向輸出,因為沒有提供 get()方法,但是 Set介面與 Collection介面的定義一致,所以其本身也不能雙向輸出
- HashSet
- 使用雜湊的方式存放內容,本身沒有順序
- 是無序排列的,而 List介面的內容插入的順序就是其儲存的順序
- 如果希望所有的內容可以自動進行排序的操作,則可以使用 Set中的第二個子類:TreeSet
- TreeSet子類是可以排序的
- 小結
- Set介面的基本作用
- 兩個子類的區別
- HashSet:雜湊存放
- TreeSet:有序存放
5.排序及重複元素說明
- TreeSet類的內容是可以排序的
- Comparable主要是進行排序的介面,一個物件陣列要想排序,則依靠 Comparable介面完成,那麼對於 TreeSet也一樣,如果要想使用 TreeSet進行排序,則物件所在的類也必須實現 Comparable介面
- String類既然可以使用 TreeSet排序,則 String類中肯定已經實現了 Comparable介面
- 如果要想取消重複元素,則需要 Object類中的兩個方法幫助
- hashCode():表示一個唯一的編碼,一般通過計算表示
- equals():進行物件的比較操作
- 如果要想使用 Set,則就必須注意以上的兩個問題
- 小結
- 一個好的類應該覆寫 Object類中的 equals()、haskCode()、toString()三個方法,實際上在 String中已經全部覆寫完成了
- Set介面依靠 hashCode()和 equals()完成重複元素的判斷,關於這一點在日後的 Map介面中也有體現
- TreeSet依靠 Comparable介面完成排序的操作
6.SortedSet介面
- TreeSet類,是可以排序的操作類,TreeSet實際上也是 SortedSet介面的一個子類,所以此介面的所有類都是可以排序的
- 小結
- 只要是以 Sorted開頭的介面基本上都是表示可以排序的介面
7.Iterator介面
- 在集合的操作中支援以下幾種方式
- Iterator
- ListIterator
- foreach輸出
- Enumeration
- Iterator介面簡介
- 集合輸出的標準操作:在使用集合輸出的時候必須形成以下的一個思路:只要是碰到了集合輸出的操作,就一定使用 Iterator介面,因為這是最標準的做法
- Iterator介面的操作原理
- Iterator是專門的迭代輸出介面,所謂的迭代輸出就是將元素一個個進行判斷,判斷其是否有內容,如果有內容則把內容取出
- 對於 Iterator而言,因為其本身是一個介面,所以要想例項化則必須依靠 Collection介面完成
- 在 Iterator介面中提供了 remove()方法,此方法的功能是刪除當前的物件
- 在實際中 Iterator是很少呼叫刪除操作的,因為其本身的功能就是輸出內容
- 對於刪除操作也有以下一個注意點
- List介面本身存在刪除方法:remove
- 如果在使用迭代輸出的過程中使用了 List中的 remove()執行刪除操作,則會出現問題
- 所以,在使用 Iterator輸出時,不要使用集合類中的 remove()方法,而只能使用 Iterator介面中的 remove方法
- 小結
- Iterator介面的功能是從前向後輸出,屬於單身的輸出
- Iterator的主要功能就是完成迭代輸出操作的
- 在使用 Iterator的時候最好不要刪除資料
8.ListIterator介面
- Iterator介面的主要功能是由前向後單身輸出,而此時如果想實現由後向前或由前向後的雙向輸出,則就必須使用 Iterator的子介面:ListIterator
- ListIterator介面定義:public interface ListIterator<E> extends Iterator<E>
- 雖然此介面可以進行雙向輸出,但是遺憾的是 Collection介面中並沒有定義可以為此類例項化的操作,只有 List介面中才存在了 ListIterator介面的例項化操作
- 【注意】在使用此操作的時候一定要注意:一定要先進行由前向後的輸出,之後才能進行由後向前的輸出
- 使用 ListIterator還可以進行增加及替換元素
- add()
- set()
- 小結
- 如果要想使用 ListIterator則只能依靠 List介面完成
- 如果要進行由後向前的輸出,則只能先進行由前向後的輸出
- 對於此介面中的增加及修改操作了解即可
9.foreach及 Enumeration介面
- 在 JDK1.5之後增加了許多新的功能,其中 foreach可以輸出陣列,實際上 foreach語法也同樣支援集合的輸出操作
- 實際上 Iterator屬於一個新的輸出介面,在最早 java剛出來的時候如果要想輸出,使用 Enumeration介面完成輸出
- 【注意】在使用 Enumeration輸出的時候一般都是直接操作 Vector類完成的
- 小結
- 在所有的輸出操作中,以 Iterator介面為最標準的輸出操作,這一點始終要記住
- 在部分舊的操作中 Enumeration依然存在
10.Map介面
- Collection的操作每次儲存的物件都是一個物件,但是在 Map中儲存的是一對物件,物件的形式是以:key ->value的形式儲存的
- Map與 Map.Entry
- Map介面的常用子類
- HashMap:無序存放的,是新的操作類,key不允許重複
- Hashtable:無序存放的,是舊的操作類,key不允許重複
- TreeMap:可以排序的 Map集合,按集合中的 Key排序,key不允許重複
- WeakHashMap:弱引用的 Map集合,當集合中的某些內容不再使用時,可以清除掉無用的資料,可以使用 gc進行回收
- IdentityHashMap:key可以重複的 Map集合
- 在 map中也可以使用 containsXxx()方法判斷指定的 key或者 value是否存在
- 返回全部的 key:Set<K> keySet()
- 返回全部的 value:Collection<V> values()
- 在 Map中也存在一個 Hashtable子類,實際上這個子類的推出時間與 Vector是一樣的,都屬於舊的類
- HashMap與 Hashtable的區別
- 在 Map中還存在一個 TreeMap的子類,此類也屬於排序類,按 key排序
- 使用 TreeMap可以方便的完成排序的操作
- 如果自定義的類要想做為 key的話,則肯定要實現 Comparable介面,指定比較的規則
- 弱引用類:WeakHashMap
- 之前的 Map子類中的資料都是使用強引用儲存的,即:裡面的內容不管是否使用都始終在集合中保留,如果希望集合可以自動清理暫不用的資料就可以使用 WeakHashMap類
- 物件的引用強度說明
- 從 JDK1.2版本開始,Java把物件的引用分為四種級別,從而使程式能更加靈活的控制物件的生命週期。這四種級別由高到低依次為:強引用、軟引用、弱引用和虛引用
- 強引用:當記憶體不足時,JVM寧可出現 OutOfMemeryError錯誤而使程式停止,也不會回收此物件來釋放空間
- 軟引用:當記憶體不足時,會回收這些物件的記憶體,用來實現記憶體敏感的調整快取
- 弱引用:無論記憶體是否緊張,被垃圾回收器發現立即回收
- 虛引用:和沒有任何引用一樣
- 小結
- 介紹了 Map的特點及基本操作
- Map與 Map.Entry的關係
- Map的子類:HashMap、Hashtable、TreeMap、WeakHashMap
- 主要功能就是查詢,根據 key找到 value
11.Map介面使用注意事項
- Map介面輸出:對於 Map介面來說,其本身是不能直接使用迭代的(例如:Iterator、foreach)進行輸出的,因為 Map中的每個位置存放的是一對值(key ->value)而 Iterator中每次只能找到一個值,所以,如果此時非要使用迭代進行輸出的話,則必須按照以下的步驟完成(以 Iterator輸出為例)
- 將 Map的例項通過 entrySet()方法變為 Set介面物件
- 通過 Set介面例項為 Iterator例項化
- 通過 Iterator迭代輸出,每個內容都是 Map.Entry的物件
- 通過 Map.Entry進行 key ->value的分離
- Map介面一般只作為查詢使用,輸出的操作屬於少數
- 在 JDK1.5之後也可以使用 foreach完成,而且更簡單
- 兩種輸出形式最終實際上還是以 Collection的形式輸出,只是以 Map.Entry作為內容的操作型別
- 在 Map中,可以使用任意的型別作為 key和 value,那麼使用非系統類也可以
- 直接使用非系統類作為 key
- 如果要使用非系統類作為 Map的 key,則此類必須覆寫 Object類中的以下兩個方法
- hashCode()
- equals
- 作為 key,或者更準確的說是作為物件的時候,實際上是依靠 hashCode()和 equals()來判斷兩個匿名物件是否相等,這一點由系統內部自動完成
- 小結
- Map可以使用迭代輸出
- map ->entrySet ->Set ->Iterator ->Map.Entry ->key和 value
- 如果使用非系統類作為 key,則一定要儲存覆寫 equals和 hashCode()方法,否則無效
14.IdentityHashMap類
- 在正常的 Map操作中,key本身是不能夠重複的
- 使用 HashMap操作的時候,key內容是不能重複的,如果現在希望 key的內容可以重複(指的重複是指兩個物件的地址不一樣)則要使用 IdentityHashMap類
- 就算是兩個物件的內容相等,是隻要地址不等,那麼就可以加入進行,key是可以重複的
15.SortedMap介面
- SortedSet,是 TreeSet的實現介面,那麼此介面可以進行排序的操作
- SortedMap也是排序的操作,之前學習過 TreeMap類,那麼此類是可以排序的
- 小結
- 認識 Map介面的子介面 SortedMap介面的基本概念
- 在此介面有很多的操作方法
- 在實際中還是以 Map介面為操作的標準
14.集合工具類:Collections
- 【面試題】Collections和 Collection的關係
- Collections類與 Collection沒有直接的關係,但是與集合中的各個介面都有操作的方法支援
- 操作方法
- 空集合操作:emptyList()/emptySet()
- 新增內容:addAll(Collection<? super T> c,T... elements),使用可變引數,所以,可以任意輸入各種型別的資料
- 二分檢索:binarySearch()
- 替換內容:replaceAll()
- 排序操作:sort(),如果要進行排序的話,則肯定物件所在的類必須實現 Comparable介面
- 交換內容:swap()
- 小結
- 在類集中為了方便集合的操作提供了 Collections類,此類與 Collection介面沒有直接的繼承或實現關係,只是對所有的介面有所支援而已
- 開發中是否使用此類沒有明確的規定,按照個人的喜好執行即可
15.Stack類
- 棧是資料結構中比較常見的一種形式,棧是採用典型的先進後出的操作方式完成的
- 每一個棧都包含一個棧頂,每次出棧是將棧頂的資料取出
- 在 Java中使用 Stack類進行棧的操作,Stack類是 Vector的子類,Stack類的定義如下:public class Stack<E> extends Vector<E>
- 如果棧中已經沒有內容了,則無法繼續出棧
16.屬性類:Properties
- 屬性是在程式中經常出現的一種形式
- 在類集中提供了一個專門的 Properties類,以完成屬性的操作:public class Properties extends Hashtable<Object, Object>
- Properties是 Hashtable的子類,則也是 Map的子類,可以使用 Map的全部操作,但是一般情況下屬性類是單獨使用的
- 設定和取得屬性:public Object setProperty(String key, String value)
- 得到屬性:public String getProperty(String key) / public String getProperty(String key, String defaultValue)
- 屬性也可以儲存到檔案之中:public void store(OutputStream out, String comments) throws IOException
- 從檔案之中讀取:public void load(InputStream inStream) throws IOException
- 同樣也可以將檔案儲存在 XML檔案中,從 XML檔案中讀取
- 小結
- 如果要進一步瞭解屬性操作,則可以繼續學習反射機制部分,發解屬性類的應用
- 屬性中的型別肯定都是字串,因為操作最方便
- 屬性可以向普通檔案或 XML檔案中儲存或讀取,按照指定格式可以向檔案中任意擴充屬性
列舉
1.列舉的作用
- 在 JDK1.5之前,JAVA可以有兩種方式定義新型別:類和介面
- 對於大部分物件導向程式設計來說,這兩種方法看起來似乎足夠我,但是在一些特殊情況下,這些方法就不適合了
- 例如:想定義一個 Color類,它只能有 Red、Green、Blue三種值,其它的任何值都是非法的,那麼 JDK1.5之前雖然可以構造這樣的程式碼,但是要做很多的工作,也有可能帶來各種不安全的問題,而在 JDK1.5之後引入的列舉型別(Enum)就能避免這些問題
- 所謂的列舉就是:規定好了指定的取值範圍,所有的內容只能從指定的範圍中取得
- 因為列舉已經指定好了範圍,所以可以使用 foreach進行全部的輸出,使用“列舉.values()”的形式取得全部的列舉內容
- 列舉還可以直接將內容在 Switch語句上使用
- 小結
- 使用列舉可以限制取值的範圍
- 使用 enum關鍵字可以定義列舉
2.Enum類
- 使用 enum關鍵字可以定義一個列舉,實際上此關鍵字表示的是 java.lang.Enum型別,即:使用 enum宣告的列舉型別,就相當於定義一個類,而此類則預設繼承 java.lang.Enum類
- public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable
- 此類定義的時候使用了泛型機制,而且實現了 Comparable介面以及 Serializable介面,證明此種型別是可以比較的,可以被序列化的
- 構造方法:protected Enum(String name, int ordinal) 構造方法中接收兩個引數:一個表示列舉的名字,另外一個表示列舉的序號
- 可以在列舉類中定義屬性及自己的構造方法,但是一旦定義有參構造之後,在宣告列舉物件的時候就必須明確的呼叫構造方法,並傳遞引數
- 對於列舉.class是 java反射機制中的內容
- 在列舉中實際已經實現好了 Comparable介面,所以列舉中的內容是可以排序的
- 小結
- Enum類的作用
- enum關鍵字與 Enum類的關係
3.類集對 Enum的支援
- EnumSet是 Set介面的子類,所以裡面的內容是無法重複的
- 在使用 EnumSet的時候是不能使用關鍵字 new為其進行例項化的,所以在此類中提供了很多的靜態方法
- EnumSet操作(基本是靜態方法)
- 將全部的集合設定到 EnumSet集合中:EnumSet.allOf()
- 只設定一個內容到集合:EnumSet.of()
- 建立時放入指定列舉型別的集合:EnumSet.noneOf()
- 建立不包含指定元素的集合:EnumSet.complementOf()
- 拷貝一個集合的內容:EnumSet.copyOf()
- 小結
- EnumMap和 EnumSet
- EnumMap是符合 Map的操作形式的
- EnumSet基本上就是都使用靜態方法完成
- 在操作中大量的使用了列舉.class,這個屬於 java反射機制
4.列舉的其它應用
- 列舉型別可以跟普通的類一樣實現一個介面,但是實現介面的時候要求列舉的每個物件都必須單獨覆寫好介面中的抽象方法
- 還可以直接在列舉中定義抽象方法,但是要求列舉中的每個物件都分別實現抽象方法
- 列舉的最大作用在於限定取值範圍