Java集合框架使用總結
前言:
本文是對
Java集合框架做了一個概括性的解說,目的是對
Java集合框架體系有個總體認識,如果你想學習具體的接口和類的使用方法,請參看
Java API文檔。
一、概述
數據結構對程序設計有著深遠的影響,在面向過程的C語言中,數據庫結構用struct來描述,而在面向對象的編程中,數據結構是用類來描述的,并且包含有對該數據結構操作的方法。
在
Java語言中,
Java語言的設計者對常用的數據結構和算法做了一些規范(接口)和實現(具體實現接口的類)。所有抽象出來的數據結構和操作(算法)統稱為
Java集合框架(
Java Collection Framework)。
Java程序員在具體應用時,不必考慮數據結構和算法實現細節,只需要用這些類創建出來一些對象,然后直接應用就可以了。這樣就大大提高了編程效率。
二、
集合框架的層次結構
Collection是集合接口
|————Set子接口:無序,不允許重復。
|————List子接口:有序,可以有重復元素。
區別:Collections是集合類
Set和List對比:
Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引起元素位置改變。
List:和數組類似,List可以動態增長,查找元素效率高,插入刪除元素效率低,因為會引起其他元素位置改變。
Set和List具體子類:
Set
|————HashSet:以哈希表的形式存放元素,插入刪除速度很快。
List
|————ArrayList:動態數組
|————LinkedList:鏈表、隊列、堆棧。
Array和
java.util.Vector
Vector是一種老的動態數組,是線程同步的,效率很低,一般不贊成使用。
三、Iterator迭代器(接口)
Iterator是獲取集合中元素的過程,實際上幫助獲取集合中的元素。
迭代器代替了
Java Collections Framework 中的 Enumeration。迭代器與枚舉有兩點不同:
迭代器允許調用方利用定義良好的語義在迭代期間從迭代器所指向的集合移除元素。
方法名稱得到了改進。
Iterator僅有一個子接口ListIterator,是列表迭代器,允許程序員按任一方向遍歷列表、迭代期間修改列表,并獲得迭代器在列表中的當前位置。ListIterator 沒有當前元素;它的光標位置 始終位于調用 previous() 所返回的元素和調用 next() 所返回的元素之間。在長度為 n 的列表中,有 n+1 個有效的索引值,從 0 到 n(包含)。
四、
集合框架之外的Map接口
Map將鍵映射到值的對象。一個映射不能包含重復的鍵;每個鍵最多只能映射一個值。
Map接口是Dictionary(字典)抽象類的替代品。
Map 接口提供三種collection 視圖,允許以鍵集、值集合或鍵-值映射關系集的形式查看某個映射的內容。映射的順序 定義為迭代器在映射的 collection 視圖中返回其元素的順序。某些映射實現可明確保證其順序,如 TreeMap 類;某些映射實現則不保證順序,如 HashMap 類。
有兩個常見的已實現的子類:
HashMap:基于哈希表的 Map 接口的實現。此實現提供所有可選的映射操作,并允許使用 null 值和 null 鍵。(除了不同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恒久不變。
TreeMap:它實現SortedMap 接口的基于紅黑樹的實現。此類保證了映射按照升序順序排列關鍵字,根據使用的構造方法不同,可能會按照鍵的類的自然順序 進行排序(參見 Comparable),或者按照創建時所提供的比較器進行排序。
Hashtable:此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非 null 對象都可以用作鍵或值。
五、線程安全類
在
集合框架中,有些類是線程安全的,這些都是JDK1.1中的出現的。在JDK1.2之后,就出現許許多多非線程安全的類。
下面是這些線程安全的同步的類:
Vector:就比ArrayList多了個同步化機制(線程安全)。
Statck:堆棧類,先進后出。
Hashtable:就比HashMap多了個線程安全。
Enumeration:枚舉,相當于迭代器。
除了這些之外,其他的都是非線程安全的類和接口。
線程安全的類其方法是同步的,每次只能一個訪問。是重量級對象,效率較低。對于非線程安全的類和接口,在多線程中需要程序員自己處理線程安全問題。
六、其他一些接口和類介紹
Dictionary和Hashtable類:
Dictionary提供鍵值映射的功能,是個抽象類。一般使用它的子類HashTable類。遍歷Hashtable類要用到枚舉。
Properties類
Properties 繼承于 Hashtable,Properties 類表示了一個持久的屬性集。Properties 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串。一般可以通過讀取properties配置文件來填充Properties對象。
參考文檔:
java api 文檔
前言:
這篇文章的目的是提醒大家對字符串三種類型做個綜合的比較,使得在使用字符串三種類的時候有個選擇依據,這樣可以極大提高程序運行的效率。如果你對這三個類已經很熟悉了,我明確告訴你,你需要看了,如果你還不明白字符串是什么,想有個大概認識,ok,繼續! 如果你向學習這三種類具體怎么用的,抱歉,請看API文檔去。
此文章參考了API文檔,但不是API文檔的拷貝,明鑒!
一、String類
String 類不是原始基本數據類型,在Java中,字符串是一個對象。
String 類代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作為此類的實例來實現。
字符串是常量;它們的值在創建之后不能改變。字符串緩沖區支持可變的字符串。因為 String 對象是不可變的,所以可以共享它們。例如:
String str = "abc";
等效于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
下面給出了一些如何使用字符串的更多例子:
System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);
既然是字符串是對象,那么任何String的變量,在沒有初始化之前,它的值都為null,其實所有的沒有初始化的對象的值都是null;所有的原始類型的變量在沒有初始化之前Java編譯器都會給出一個默認值。
Java 語言提供對字符串串聯符號("+")和其他對象到字符串的轉換的特殊支持。字符串串聯是通過 StringBuilder(或 StringBuffer)類及其 append 方法實現的。字符串轉換是通過 toString 方法實現的,該方法由 Object 類定義,并可被 Java 中所有類繼承。有關字符串串聯和轉換的更多信息,請參閱 Gosling、Joy 和 Steele 合著的《The Java Language Specification》。
除非另行說明,否則將 null 參數傳遞給此類中的構造方法或方法都會拋出 NullPointerException。
String 表示一個 UTF-16 格式的字符串,其中的增補字符 由代理項對 表示(有關詳細信息,請參閱 Character 類中的 Unicode 字符表示形式)。索引值是指 char 代碼單元,因此增補字符在 String 中占用兩個位置。
String 類提供處理 Unicode 代碼點(即字符)和 Unicode 代碼單元(即 char 值)的方法。
String使用的陷阱:String一經初始化后,就不會在改變其內容了。對String字符串的操作實際上對其副本(原始拷貝)的操作,原來的字符串一點都沒有改變。比如:
string s="a"; //創建了一個字符串
s=s+"b"; //實際上原來的"a"字符串對象已經丟棄了,現在又產生了一個字符串s+"b"(也就是"ab")。如果多次執行這些改變串內容的操作,會導致大量副本字符串對象存留在內存中,降低效率。如果這樣的操作放到循環中,會極大影響程序的性能。
相反,StringBuffer類是對原字符串本身操作的,可以對字符串進行修改而不產生副本拷貝。可以在循環中使用。
因此,如果要對字符串做修改處理等操作,最好避免直接用String類型。可以選用StringBuffer類型。
二、StringBuffer類
StringBuffer類是線程安全的可變字符序列。一個類似于 String 的字符串緩沖區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。
可將字符串緩沖區安全地用于多個線程。可以在必要時對這些方法進行同步,因此任意特定實例上的所有操作就好像是以串行順序發生的,該順序與所涉及的每個線程進行的方法調用順序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將給定的數據轉換成字符串,然后將該字符串的字符追加或插入到字符串緩沖區中。append 方法始終將這些字符添加到緩沖區的末端;而 insert 方法則在指定的點添加字符。
例如,如果 z 引用一個當前內容為 "start" 的字符串緩沖區對象,則此方法調用 z.append("le") 會使字符串緩沖區包含 "startle",而 z.insert(4, "le") 將更改字符串緩沖區,使之包含 "starlet"。
通常,如果 sb 引用 StringBuilder 的一個實例,則 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。
當發生與源序列有關的操作(如源序列中的追加或插入操作)時,該類只在執行此操作的字符串緩沖區上而不是在源上實現同步。
每個字符串緩沖區都有一定的容量。只要字符串緩沖區所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩沖區數組。如果內部緩沖區溢出,則此容量自動增大。從 JDK 5 開始,為該類補充了一個單個線程使用的等價類,即 StringBuilder。與該類相比,通常應該優先使用 StringBuilder 類,因為它支持所有相同的操作,但由于它不執行同步,所以速度更快。
三、StringBuilder類
StringBuilder類是一個可變的字符序列。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區被單個線程使用的時候(這種情況很普遍)。如果可能,建議優先采用該類,因為在大多數實現中,它比 StringBuffer 要快。
在 StringBuilder 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將給定的數據轉換成字符串,然后將該字符串的字符追加或插入到字符串生成器中。append 方法始終將這些字符添加到生成器的末端;而 insert 方法則在指定的點添加字符。
例如,如果 z 引用一個當前內容為 "start" 的字符串的生成器對象,則該方法調用 z.append("le") 將使字符串生成器包含 "startle",而 z.insert(4, "le") 將更改字符串生成器,使之包含 "starlet"。
通常,如果 sb 引用 StringBuilder 的實例,則 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。每個字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩沖區。如果內部緩沖區溢出,則此容量自動增大。
將 StringBuilder 的實例用于多個線程是不安全的。如果需要這樣的同步,則建議使用 StringBuffer。
四、字符串的比較
”==“比較此字符串是否引用同一個實例,是否指向同一個內存地址。
equals(Object anObject)比較此字符串是否是同一個實例,是否指向同一個內存地址。
equalsIgnoreCase(String anotherString)將此 String 與另一個 String 進行比較,不考慮大小寫。
參考資料:
java api 中文文檔