[Java] 集合框架

集合接口繼承樹:java

 

比較繁瑣的圖:數據庫

簡化圖:編程

Java 2集合框架圖
集合接口:6個接口(短虛線表示),表示不一樣集合類型,是集合框架的基礎。
抽象類:5個抽象類(長虛線表示),對集合接口的部分實現。可擴展爲自定義集合類。
實現類:8個實現類(實線表示),對接口的具體實現。
在很大程度上,一旦您理解了接口,您就理解了框架。雖然您總要建立接口特定的實現,但訪問實際集合的方法應該限制在接口方法的使用上;所以,容許您更改基本的數據結構而沒必要改變其它代碼。數組

· Collection 接口是一組容許重複的對象。
· Set 接口繼承 Collection,但不容許重複,使用本身內部的一個排列機制。
· List 接口繼承 Collection,容許重複,以元素安插的次序來放置元素,不會從新排列。
· Map接口是一組成對的鍵-值對象,即所持有的是key-value pairs。Map中不能有重複的key。擁有本身的內部排列機制。
· 容器中的元素類型都爲Object。從容器取得元素時,必須把它轉換成原來的類型。緩存

 

集合接口 1.Collection 接口
Collection接口:
    |
    + -- Set接口:一個不包含重複元素的 collection。更正式地說,set 不包含知足 e1.equals(e2) 的元素對 e1 和 e2,並
    |      |     且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學上的 set 抽象。
    |      |
    |      + -- HashSet:此類實現 Set 接口,由哈希表(其實是一個 HashMap 實例)支持。它不保證 set 的迭代順序;
    |      |    特別是它不保證該順序恆久不變。此類容許使用 null 元素。此類爲基本操做提供了穩定性能,此實現不是同
    |      |    步的。
    |      |
    |      + -- LinkedHashSet:具備可預知迭代順序的 Set 接口的哈希表和連接列表實現。此實現與 HashSet 的不一樣以外在
    |      |    於,後者維護着一個運行於全部條目的雙重連接列表。此連接列表定義了迭代順序,即按照將元素插入到 set
    |      |    中 的順序(插入順序)進行迭代。注意,插入順序不 受在 set 中從新插入的 元素的影響。此實現不是同步
    |      |    的。 
    |      |
    |      + -- TreeSet:基於 TreeMap 的 NavigableSet 實現。使用元素的天然順序對元素進行排序,或者根據建立 set 時
    |           提供的 Comparator 進行排序,具體取決於使用的構造方法。此實現爲基本操做(add、remove 和 contains)
    |           提供受保證的 log(n) 時間開銷。此實現不是同步的。
    |
    + -- List接口:有序的 collection(也稱爲序列)。此接口的用戶能夠對列表中每一個元素的插入位置進行精確地控制。用戶
           |      能夠根據元素的整數索引(在列表中的位置)訪問元素,並搜索列表中的元素。
           |
           + -- ArrayList:List 接口的大小可變數組的實現。實現了全部可選列表操做,並容許包括 null 在內的全部元素。
           |    除了實現 List 接口外,此類還提供一些方法來操做內部用來存儲列表的數組的大小。(此類大體上等同於 
           |    Vector 類,除了此類是不一樣步的。)每一個 ArrayList 實例都有一個容量。該容量是指用來存儲列表元素的數
           |    組的大小。它老是至少等於列表的大小。隨着向 ArrayList 中不斷添加元素,其容量也自動增加。並未指定增
           |    長策略的細節,由於這不僅是添加元素會帶來分攤固定時間開銷那樣簡單。此實現不是同步的。
           |
           + -- LinkedList:List 接口的連接列表實現。實現全部可選的列表操做,而且容許全部元素(包括 null)。除了實
           |    現 List 接口外,LinkedList 類還爲在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方
           |    法。這些操做容許將連接列表用做堆棧、隊列或雙端隊列。提供先進先出隊列操做(FIFO)。此實現不是同步的。
           |
           + -- Vector:Vector 類能夠實現可增加的對象數組。與數組同樣,它包含可使用整數索引進行訪問的組件。可是
                ,Vector 的大小能夠根據須要增大或縮小,以適應建立 Vector 後進行添加或移除項的操做。此實現是同步的
 
 

 


用於表示任何對象或元素組。想要儘量以常規方式處理一組元素時,就使用這一接口。

(1) 單元素添加、刪除操做:
        boolean add(Object o):將對象添加給集合
        boolean remove(Object o): 若是集合中有與o相匹配的對象,則刪除對象o
(2) 查詢操做:
        int size() :返回當前集合中元素的數量
        boolean isEmpty() :判斷集合中是否有任何元素
        boolean contains(Object o) :查找集合中是否含有對象o
        Iterator iterator() :返回一個迭代器,用來訪問集合中的各個元素
(3) 組操做 :做用於元素組或整個集合
        boolean containsAll(Collection c): 查找集合中是否含有集合c 中全部元素
        boolean addAll(Collection c) : 將集合c 中全部元素添加給該集合
        void clear(): 刪除集合中全部元素
        void removeAll(Collection c) : 從集合中刪除集合c 中的全部元素
        void retainAll(Collection c) : 從集合中刪除集合c 中不包含的元素
(4) Collection轉換爲Object數組 :
        Object[] toArray() :返回一個內含集合全部元素的array
        Object[] toArray(Object[] a) :返回一個內含集合全部元素的array。運行期返回的array和參數a的型別相同,須要轉換爲正確型別。
此外,您還能夠把集合轉換成其它任何其它的對象數組。可是,您不能直接把集合轉換成基本數據類型的數組,由於集合必須持有對象。
「斜體接口方法是可選的。由於一個接口實現必須實現全部接口方法,調用程序就須要一種途徑來知道一個可選的方法是否是不受支持。若是調用一種可選方法 時,一個 UnsupportedOperationException 被拋出,則操做失敗,由於方法不受支持。此異常類繼承 RuntimeException 類,避免了將全部集合操做放入 try-catch 塊。」
Collection不提供get()方法。若是要遍歷Collectin中的元素,就必須用Iterator。
1.1.AbstractCollection 抽象類
AbstractCollection 類提供具體「集合框架」類的基本功能。雖然您能夠自行實現 Collection 接口的全部方法,可是,除了iterator()和size()方法在恰當的子類中實現之外,其它全部方法都由 AbstractCollection 類來提供實現。若是子類不覆蓋某些方法,可選的如add()之類的方法將拋出異常。
1.2.Iterator 接口
Collection 接口的iterator()方法返回一個 Iterator。Iterator接口方法能以迭代方式逐個訪問集合中各個元素,並安全的從Collection 中除去適當的元素。

(1) boolean hasNext(): 判斷是否存在另外一個可訪問的元素
     Object next(): 返回要訪問的下一個元素。若是到達集合結尾,則拋出NoSuchElementException異常。
(2) void remove(): 刪除上次訪問返回的對象。本方法必須緊跟在一個元素的訪問後執行。若是上次訪問後集合已被修改,方法將拋出IllegalStateException。
「Iterator中刪除操做對底層Collection也有影響。」
迭代器是 故障快速修復(fail-fast)的。這意味着,當另外一個線程修改底層集合的時候,若是您正在用 Iterator 遍歷集合,那麼,Iterator就會拋出 ConcurrentModificationException (另外一種 RuntimeException異常)異常並馬上失敗

2.List接口 List 接口繼承了 Collection 接口以定義一個容許重複項的有序集合。該接口不但可以對列表的一部分進行處理,還添加了面向位置的操做。 (1) 面向位置的操做包括插入某個元素或 Collection 的功能,還包括獲取、除去或更改元素的功能。在 List 中搜索元素能夠從列表的頭部或尾部開始,若是找到元素,還將報告元素所在的位置 : void add(int index, Object element): 在指定位置index上添加元素element boolean addAll(int index, Collection c): 將集合c的全部元素添加到指定位置index Object get(int index): 返回List中指定位置的元素 int indexOf(Object o): 返回第一個出現元素o的位置,不然返回-1 int lastIndexOf(Object o) :返回最後一個出現元素o的位置,不然返回-1 Object remove(int index) :刪除指定位置上的元素 Object set(int index, Object element) :用元素element取代位置index上的元素,而且返回舊的元素 (2) List 接口不但以位置序列迭代的遍歷整個列表,還能處理集合的子集: ListIterator listIterator() : 返回一個列表迭代器,用來訪問列表中的元素 ListIterator listIterator(int index) : 返回一個列表迭代器,用來從指定位置index開始訪問列表中的元素 List subList(int fromIndex, int toIndex) :返回從指定位置fromIndex(包含)到toIndex(不包含)範圍中各個元素的列表視圖 「對子列表的更改(如 add()、remove() 和 set() 調用)對底層 List 也有影響。」
2.1.ListIterator接口 ListIterator 接口繼承 Iterator 接口以支持添加或更改底層集合中的元素,還支持雙向訪問。ListIterator沒有當前位置,光標位於調用previous和next方法返回的值之間。一個長度爲n的列表,有n+1個有效索引值: Element(0) Element(1) Element(2) ... Element(n) Index 1 2 3 ... n+1 (1) void add(Object o): 將對象o添加到當前位置的前面 void set(Object o): 用對象o替代next或previous方法訪問的上一個元素。若是上次調用後列表結構被修改了,那麼將拋出IllegalStateException 異常。 (2) boolean hasPrevious(): 判斷向後迭代時是否有元素可訪問 Object previous():返回上一個對象 int nextIndex(): 返回下次調用next方法時將返回的元素的索引 int previousIndex(): 返回下次調用previous方法時將返回的元素的索引 「正常狀況下,不用ListIterator改變某次遍歷集合元素的方向 — 向前或者向後。雖然在技術上能夠實現,但previous() 後馬上調用next(),返回的是同一個元素。把調用 next()和previous()的順序顛倒一下,結果相同。」 「咱們還須要稍微再解釋一下 add() 操做。添加一個元素會致使新元素馬上被添加到隱式光標的前面。所以,添加元素後調用 previous() 會返回新元素,而調用 next() 則不起做用,返回添加操做以前的下一個元素。」
2.2.AbstractList和AbstractSequentialList抽象類 有兩個抽象的 List 實現類:AbstractList 和 AbstractSequentialList。像 AbstractSet 類同樣,它們覆蓋了 equals() 和 hashCode() 方法以確保兩個相等的集合返回相同的哈希碼。若兩個列表大小相等且包含順序相同的相同元素,則這兩個列表相等。這裏的 hashCode() 實如今 List 接口定義中指定,而在這裏實現。 除了equals()和hashCode(),AbstractList和 AbstractSequentialList實現了其他 List 方法的一部分。由於數據的隨機訪問和順序訪問是分別實現的,使得具體列表實現的建立更爲容易。須要定義的一套方法取決於您但願支持的行爲。您永遠沒必要親自 提供的是 iterator方法的實現。
2.3. LinkedList類和ArrayList類 在「集合框架 」中有兩種常規的 List 實現:ArrayList 和 LinkedList。使用兩種 List 實現的哪種取決於您特定的須要。若是要支持隨機訪問,而沒必要在除尾部的任何位置插入或除去元素,那麼,ArrayList 提供了可選的集合。但若是,您要頻繁的從列表的中間位置添加和除去元素,而只要順序的訪問列表元素,那麼,LinkedList 實現更好。 「ArrayList 和 LinkedList 都實現 Cloneable 接口,都提供了兩個構造函數,一個無參的,一個接受另外一個Collection」
2.3.1. LinkedList類 LinkedList類添加了一些處理列表兩端元素的方法。 (1) void addFirst(Object o): 將對象o添加到列表的開頭 void addLast(Object o):將對象o添加到列表的結尾 (2) Object getFirst(): 返回列表開頭的元素 Object getLast(): 返回列表結尾的元素 (3) Object removeFirst(): 刪除而且返回列表開頭的元素 Object removeLast():刪除而且返回列表結尾的元素 (4) LinkedList(): 構建一個空的連接列表 LinkedList(Collection c): 構建一個連接列表,而且添加集合c的全部元素 「使用這些新方法,您就能夠輕鬆的把 LinkedList 看成一個堆棧、隊列或其它面向端點的數據結構。」
2.3.2. ArrayList類 ArrayList類封裝了一個動態再分配的Object[]數組。每一個ArrayList對象有一個capacity。這個capacity表示存儲列表中元素的數組的容量。當元素添加到ArrayList時,它的capacity在常量時間內自動增長。 在向一個ArrayList對象添加大量元素的程序中,可以使用ensureCapacity方法增長capacity。這能夠減小增長重分配的數量。 (1) void ensureCapacity(int minCapacity): 將ArrayList對象容量增長minCapacity (2) void trimToSize(): 整理ArrayList對象容量爲列表當前大小。程序可以使用這個操做減小ArrayList對象存儲空間。

package collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class arrayListDemo {
    public static void main(String[] args) {
        // int i = 1;
        List list = new ArrayList();

        list.add("a");
        list.add("b");
        list.add("c");

        list.add(1, "zzzz");
        System.out.println(list);

        String obj = (String) list.get(2);
        System.out.println(obj);

        int i = list.indexOf("ccc");
        System.out.println(i);

        list.remove("b");
        System.out.println(list);

        int size = list.size();
        System.out.println(size);

        for (int j = 0; j < list.size(); j++) {
            String obj1 = (String) list.get(j);
            System.out.println(obj1);
        }

        Iterator itr = list.iterator();
        while (itr.hasNext()) {

            String obj2 = (String) itr.next();
            System.out.println(obj2);

/*注意:在迭代器中要刪除某個元素,必須用迭代器的方法刪除,不能夠用list的方法*/
        }
    
        System.out.println(list);
    }
}
結果:

[a, zzzz, b, c]
b
-1
[a, zzzz, c]
3
a
zzzz
c
a
zzzz
c
[a, zzzz, c]安全

 


2.3.2.1. RandomAccess接口 一個特徵接口。該接口沒有任何方法,不過你可使用該接口來測試某個集合是否支持有效的隨機訪問。ArrayList和Vector類用於實現該接口
3.Set接口 Set 接口繼承 Collection 接口,並且它不容許集合中存在重複項,每一個具體的 Set 實現類依賴添加的對象的 equals()方法來檢查獨一性。Set接口沒有引入新方法,因此Set就是一個Collection,只不過其行爲不一樣。 3.1. Hash表 Hash表是一種數據結構,用來查找對象。Hash表爲每一個對象計算出一個整數,稱爲Hash Code(哈希碼)。Hash表是個連接式列表的陣列。每一個列表稱爲一個buckets(哈希表元)。對象位置的計算 index = HashCode % buckets (HashCode爲對象哈希碼,buckets爲哈希表元總數)。 當你添加元素時,有時你會遇到已經填充了元素的哈希表元,這種狀況稱爲Hash Collisions(哈希衝突)。這時,你必須判斷該元素是否已經存在於該哈希表中。 若是哈希碼是合理地隨機分佈的,而且哈希表元的數量足夠大,那麼哈希衝突的數量就會減小。同時,你也能夠經過設定一個初始的哈希表元數量來更好地控制哈 希表的運行。初始哈希表元的數量爲 buckets = size * 150% + 1 (size爲預期元素的數量)。 若是哈希 表中的元素放得太滿,就必須進行rehashing(再哈希)。再哈希使哈希表元數增倍,並將原有的對象從新導入新的哈希表元中,而原始的哈希表元被刪 除。load factor(加載因子)決定什麼時候要對哈希表進行再哈希。在Java編程語言中,加載因子默認值爲0.75,默認哈希表元爲101。
3.2. Comparable接口和Comparator接口 在「集合框架」中有兩種比較接口:Comparable接口和Comparator接口。像String和Integer等Java內建類實現 Comparable接口以提供必定排序方式,但這樣只能實現該接口一次。對於那些沒有實現Comparable接口的類、或者自定義的類,您能夠經過 Comparator接口來定義您本身的比較方式。
3.2.1. Comparable接口 在java.lang包中,Comparable接口適用於一個類有天然順序的時候。假定對象集合是同一類型,該接口容許您把集合排序成天然順序。 (1) int compareTo(Object o): 比較當前實例對象與對象o,若是位於對象o以前,返回負值,若是兩個對象在排序中位置相同,則返回0,若是位於對象o後面,則返回正值 在 Java 2 SDK版本1.4中有二十四個類實現Comparable接口。下表展現了8種基本類型的天然排序。雖然一些類共享同一種天然排序,但只有相互可比的類才能排序。 類 排序 BigDecimal,BigInteger,Byte, Double, Float,Integer,Long,Short 按照數字大小排序 Character 按 Unicode 值的數字大小排序 String 按字符串中字符 Unicode 值排序 利用Comparable接口建立您本身的類的排序順序,只是實現compareTo()方法的問題。一般就是依賴幾個數據成員的天然排序。同時類也應該覆蓋equals()和hashCode()以確保兩個相等的對象返回同一個哈希碼。
3.2.2. Comparator接口 若一個類不能用於實現java.lang.Comparable,或者您不喜歡缺省的Comparable行爲並想提供本身的排序順序(可能多種排序方式),你能夠實現Comparator接口,從而定義一個比較器。 (1)int compare(Object o1, Object o2): 對兩個對象o1和o2進行比較,若是o1位於o2的前面,則返回負值,若是在排序順序中認爲o1和o2是相同的,返回0,若是o1位於o2的後面,則返回正值 「與Comparable類似,0返回值不表示元素相等。一個0返回值只是表示兩個對象排在同一位置。由Comparator用戶決定如何處理。若是兩個不相等的元素比較的結果爲零,您首先應該確信那就是您要的結果,而後記錄行爲。」 (2)boolean equals(Object obj): 指示對象obj是否和比較器相等。 「該方法覆寫Object的equals()方法,檢查的是Comparator實現的等同性,不是處於比較狀態下的對象。」
3.3. SortedSet接口 「集合框架」提供了個特殊的Set接口:SortedSet,它保持元素的有序順序。SortedSet接口爲集的視圖(子集)和它的兩端(即頭和尾) 提供了訪問方法。當您處理列表的子集時,更改視圖會反映到源集。此外,更改源集也會反映在子集上。發生這種狀況的緣由在於視圖由兩端的元素而不是下標元素 指定,因此若是您想要一個特殊的高端元素(toElement)在子集中,您必須找到下一個元素。 添加到SortedSet實現類的元素必須實現Comparable接口,不然您必須給它的構造函數提供一個Comparator接口的實現。 TreeSet類是它的惟一一份實現。 「由於集必須包含惟一的項,若是添加元素時比較兩個元素致使了0返回值(經過Comparable的compareTo()方法或Comparator 的compare()方法),那麼新元素就沒有添加進去。若是兩個元素相等,那還好。但若是它們不相等的話,您接下來就應該修改比較方法,讓比較方法和 equals() 的效果一致。」 (1) Comparator comparator(): 返回對元素進行排序時使用的比較器,若是使用Comparable接口的compareTo()方法對元素進行比較,則返回null (2) Object first(): 返回有序集合中第一個(最低)元素 (3) Object last(): 返回有序集合中最後一個(最高)元素 (4) SortedSet subSet(Object fromElement, Object toElement): 返回從fromElement(包括)至toElement(不包括)範圍內元素的SortedSet視圖(子集) (5) SortedSet headSet(Object toElement): 返回SortedSet的一個視圖,其內各元素皆小於toElement (6) SortedSet tailSet(Object fromElement): 返回SortedSet的一個視圖,其內各元素皆大於或等於fromElement
3.4. AbstractSet抽象類 AbstractSet類覆蓋了Object類的equals()和hashCode()方法,以確保兩個相等的集返回相同的哈希碼。若兩個集大小相等 且包含相同元素,則這兩個集相等。按定義,集的哈希碼是集中元素哈希碼的總和。所以,不論集的內部順序如何,兩個相等的集會有相同的哈希碼。
3.4.1. Object類 (1) boolean equals(Object obj): 對兩個對象進行比較,以便肯定它們是否相同 (2) int hashCode(): 返回該對象的哈希碼。相同的對象必須返回相同的哈希碼
3.5. HashSet類類和TreeSet類 「集合框架」支持Set接口兩種普通的實現:HashSet和TreeSet(TreeSet實現SortedSet接口)。在更多狀況下,您會使用 HashSet 存儲重複自由的集合。考慮到效率,添加到 HashSet 的對象須要採用恰當分配哈希碼的方式來實現hashCode()方法。雖然大多數系統類覆蓋了 Object中缺省的hashCode()和equals()實現,但建立您本身的要添加到HashSet的類時,別忘了覆蓋 hashCode()和equals()。 當您要從集合中以有序的方式插入和抽取元素時,TreeSet實現會有用處。爲了能順利進行,添加到TreeSet的元素必須是可排序的。
3.5.1.HashSet類 (1) HashSet(): 構建一個空的哈希集 (2) HashSet(Collection c): 構建一個哈希集,而且添加集合c中全部元素 (3) HashSet(int initialCapacity): 構建一個擁有特定容量的空哈希集 (4) HashSet(int initialCapacity, float loadFactor): 構建一個擁有特定容量和加載因子的空哈希集。LoadFactor是0.0至1.0之間的一個數
package collection;

import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    
    public void hashSetExample(){
        Set vehicles = new HashSet();
        
        //聲明一些 string items
        String item_1 = "Car";
        String item_2 = "Bicycle";
        String item_3 = "Tractor";
        
        boolean result;
        
        //添加items 到 Set
        result = vehicles.add(item_1);
        System.out.println(item_1  +  "        :" + result);
        
        result = vehicles.add(item_2);
        System.out.println(item_2  +  "        :" + result);
        
        result = vehicles.add(item_3);
        System.out.println(item_3  +  "        :" + result);
        
        //咱們再添加一遍item_1
        result = vehicles.add(item_1);
        System.out.println(item_1  +  ":" + result);
        
        //添加null
        result = vehicles.add(null);
        System.out.println("null         :" + result);
        
        //再次添加null
        result = vehicles.add(null);
        System.out.println("null         :" + result);
        
    }
    public static void main(String[] args){
        new HashSetDemo().hashSetExample();
    } 
}
結果:
Car        :true
Bicycle        :true
Tractor        :true
Car:false
null         :true
null         :false
3.5.2. TreeSet類
(1) TreeSet():構建一個空的樹集
(2) TreeSet(Collection c): 構建一個樹集,而且添加集合c中全部元素
(3) TreeSet(Comparator c): 構建一個樹集,而且使用特定的比較器對其元素進行排序
「comparator比較器沒有任何數據,它只是比較方法的存放器。這種對象有時稱爲函數對象。函數對象一般在「運行過程當中」被定義爲匿名內部類的一個實例。」
TreeSet(SortedSet s): 構建一個樹集,添加有序集合s中全部元素,而且使用與有序集合s相同的比較器排序
3.6. LinkedHashSet類 LinkedHashSet擴展HashSet。若是想跟蹤添加給HashSet的元素的順序,LinkedHashSet實現會有幫助。 LinkedHashSet的迭代器按照元素的插入順序來訪問各個元素。它提供了一個能夠快速訪問各個元素的有序集合。同時,它也增長了實現的代價,由於 哈希表元中的各個元素是經過雙重連接式列表連接在一塊兒的。 (1) LinkedHashSet(): 構建一個空的連接式哈希集 (2) LinkedHashSet(Collection c): 構建一個連接式哈希集,而且添加集合c中全部元素 (3) LinkedHashSet(int initialCapacity): 構建一個擁有特定容量的空連接式哈希集 (4) LinkedHashSet(int initialCapacity, float loadFactor): 構建一個擁有特定容量和加載因子的空連接式哈希集。LoadFactor是0.0至1.0之間的一個數 「爲優化HashSet空間的使用,您能夠調優初始容量和負載因子。TreeSet不包含調優選項,由於樹老是平衡的。」
4. Map接口
Map接口:
    |
    + -- WeakHashMap: 以弱鍵 實現的基於哈希表的 Map。在 WeakHashMap 中,當某個鍵再也不正常使用時,將自動移除其條
    |      目。更精確地說,對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成爲可終止的,被終
    |      止,而後被回收。丟棄某個鍵時,其條目從映射中有效地移除,所以,該類的行爲與其餘的 Map 實現有所不一樣。此實現
    |      不是同步的。
    |
    + -- TreeMap:該映射根據其鍵的天然順序進行排序,或者根據建立映射時提供的 Comparator 進行排序,具體取決於使用的
    |    構造方法。此實現不是同步的。
    |
    + -- HashMap:基於哈希表的 Map 接口的實現。此實現提供全部可選的映射操做,並容許使用 null 值和 null 鍵。(除了       
    |        非同步和容許使用 null 以外,HashMap 類與 Hashtable 大體相同。)此類不保證映射的順序,特別是它不保證該順    
    |       序恆久不變。此實現不是同步的。
    |
    +-- SortedMap: 進一步提供關於鍵的整體排序 的 Map。該映射是根據其鍵的天然順序進行排序的,或者根據一般在建立有
         序映射時提供的 Comparator 進行排序。對有序映射的 collection 視圖(由 entrySet、keySet 和 values 方法返回
         )進行迭代時,此順序就會反映出來。要採用此排序方式,還須要提供一些其餘操做(此接口是 SortedSet 的對應映
         射)。
 
 

Map接口不是Collection接口的繼承。Map接口用於維護鍵/值對(key/value pairs)。該接口描述了從不重複的鍵到值的映射。

(1) 添加、刪除操做:
        Object put(Object key, Object value): 將互相關聯的一個關鍵字與一個值放入該映像。若是該關鍵字已經存在,那麼與此關鍵字相關的新值將取代舊值。方法返回關鍵字的舊值,若是關鍵字原先並不存在,則返回null
        Object remove(Object key): 從映像中刪除與key相關的映射
        void putAll(Map t): 未來自特定映像的全部元素添加給該映像
        void clear(): 從映像中刪除全部映射
「鍵和值均可覺得null。可是,您不能把Map做爲一個鍵或值添加給自身。」
(2) 查詢操做:
        Object get(Object key): 得到與關鍵字key相關的值,而且返回與關鍵字key相關的對象,若是沒有在該映像中找到該關鍵字,則返回null
        boolean containsKey(Object key): 判斷映像中是否存在關鍵字key
        boolean containsValue(Object value): 判斷映像中是否存在值value
        int size(): 返回當前映像中映射的數量
        boolean isEmpty() :判斷映像中是否有任何映射
(3) 視圖操做 :處理映像中鍵/值對組
        Set keySet(): 返回映像中全部關鍵字的視圖集
「由於映射中鍵的集合必須是惟一的,您用Set支持。你還能夠從視圖中刪除元素,同時,關鍵字和它相關的值將從源映像中被刪除,可是你不能添加任何元素。」
        Collection values():返回映像中全部值的視圖集
「由於映射中值的集合不是惟一的,您用Collection支持。你還能夠從視圖中刪除元素,同時,值和它的關鍵字將從源映像中被刪除,可是你不能添加任何元素。」
        Set entrySet(): 返回Map.Entry對象的視圖集,即映像中的關鍵字/值對
「由於映射是惟一的,您用Set支持。你還能夠從視圖中刪除元素,同時,這些元素將從源映像中被刪除,可是你不能添加任何元素。」
4.1. Map.Entry接口 Map的entrySet()方法返回一個實現Map.Entry接口的對象集合。集合中每一個對象都是底層Map中一個特定的鍵/值對。 經過這個集合的迭代器,您能夠得到每個條目(惟一獲取方式)的鍵或值並對值進行更改。當條目經過迭代器返回後,除非是迭代器自身的remove()方 法或者迭代器返回的條目的setValue()方法,其他對源Map外部的修改都會致使此條目集變得無效,同時產生條目行爲未定義。 (1) Object getKey(): 返回條目的關鍵字 (2) Object getValue(): 返回條目的值 (3) Object setValue(Object value): 將相關映像中的值改成value,而且返回舊值
4.2. SortedMap接口 「集合框架」提供了個特殊的Map接口:SortedMap,它用來保持鍵的有序順序。 SortedMap接口爲映像的視圖(子集),包括兩個端點提供了訪問方法。除了排序是做用於映射的鍵之外,處理SortedMap和處理 SortedSet同樣。 添加到SortedMap實現類的元素必須實現Comparable接口,不然您必須給它的構造函數提供一個Comparator接口的實現。 TreeMap類是它的惟一一份實現。 「由於對於映射來講,每一個鍵只能對應一個值,若是在添加一個鍵/值對時比較兩個鍵產生了0返回值(經過Comparable的compareTo()方 法或經過Comparator的compare()方法),那麼,原始鍵對應值被新的值替代。若是兩個元素相等,那還好。但若是不相等,那麼您就應該修改 比較方法,讓比較方法和 equals() 的效果一致。」 (1) Comparator comparator(): 返回對關鍵字進行排序時使用的比較器,若是使用Comparable接口的compareTo()方法對關鍵字進行比較,則返回null (2) Object firstKey(): 返回映像中第一個(最低)關鍵字 (3) Object lastKey(): 返回映像中最後一個(最高)關鍵字 (4) SortedMap subMap(Object fromKey, Object toKey): 返回從fromKey(包括)至toKey(不包括)範圍內元素的SortedMap視圖(子集) (5) SortedMap headMap(Object toKey): 返回SortedMap的一個視圖,其內各元素的key皆小於toKey (6) SortedSet tailMap(Object fromKey): 返回SortedMap的一個視圖,其內各元素的key皆大於或等於fromKey
4.3. AbstractMap抽象類 和其它抽象集合實現類似,AbstractMap 類覆蓋了equals()和hashCode()方法以確保兩個相等映射返回相同的哈希碼。若是兩個映射大小相等、包含一樣的鍵且每一個鍵在這兩個映射中對 應的值都相同,則這兩個映射相等。映射的哈希碼是映射元素哈希碼的總和,其中每一個元素是Map.Entry接口的一個實現。所以,不論映射內部順序如何, 兩個相等映射會報告相同的哈希碼。
4.4. HashMap類和TreeMap類 「集合框架」提供兩種常規的 Map實現:HashMap和TreeMap (TreeMap實現SortedMap接口)。在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但若是您要按天然順序或自定義順序遍歷鍵,那麼TreeMap會更好。使用HashMap要求添加的鍵類明肯定義了hashCode()和 equals()的實現。 這個TreeMap沒有調優選項,由於該樹總處於平衡狀態。
4.4.1. HashMap類 爲了優化HashMap空間的使用,您能夠調優初始容量和負載因子。 (1) HashMap(): 構建一個空的哈希映像 (2) HashMap(Map m): 構建一個哈希映像,而且添加映像m的全部映射 (3) HashMap(int initialCapacity): 構建一個擁有特定容量的空的哈希映像 (4) HashMap(int initialCapacity, float loadFactor): 構建一個擁有特定容量和加載因子的空的哈希映像
package collection;

import java.util.HashMap;
import java.util.Iterator;

public class HashMapDemo {
    public static void main(String[] args) {
        // 在hashmap中的對象是無序的
        HashMap hm = new HashMap();
        hm.put("a", "h1");
        hm.put("b", "h2");
        hm.put("c", "h3");
        
        // 測試是否包含關鍵字"a"
        System.out.println(hm.containsKey("a"));
        System.out.println(hm.containsKey("d"));

        System.out.println(hm.get("a"));
        System.out.println(hm.entrySet());
        
        Iterator it = hm.entrySet().iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        // Set keySet()返回關鍵字的集合
        it = hm.keySet().iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}
結果:
true
false
h1
[b=h2, c=h3, a=h1]
b=h2
c=h3
a=h1
b
c
a
4.4.2. TreeMap類
TreeMap沒有調優選項,由於該樹總處於平衡狀態。
(1) TreeMap():構建一個空的映像樹
(2) TreeMap(Map m): 構建一個映像樹,而且添加映像m中全部元素
(3) TreeMap(Comparator c): 構建一個映像樹,而且使用特定的比較器對關鍵字進行排序
(4) TreeMap(SortedMap s): 構建一個映像樹,添加映像樹s中全部映射,而且使用與有序映像s相同的比較器排序
4.5. LinkedHashMap類 LinkedHashMap擴展HashMap,以插入順序將關鍵字/值對添加進連接哈希映像中。象LinkedHashSet同樣,LinkedHashMap內部也採用雙重連接式列表。 (1) LinkedHashMap(): 構建一個空連接哈希映像 (2) LinkedHashMap(Map m): 構建一個連接哈希映像,而且添加映像m中全部映射 (3) LinkedHashMap(int initialCapacity): 構建一個擁有特定容量的空的連接哈希映像 (4) LinkedHashMap(int initialCapacity, float loadFactor): 構建一個擁有特定容量和加載因子的空的連接哈希映像 (5) LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder): 構建一個擁有特定容量、加載因子和訪問順序排序的空的連接哈希映像 「若是將accessOrder設置爲true,那麼連接哈希映像將使用訪問順序而不是插入順序來迭 代各個映像。每次調用get或者put方法時,相關的映射便從它的當前位置上刪除,而後放到連接式映像列表的結尾處(只有連接式映像列表中的位置纔會受到影響,哈希表元則不受影響。哈希表映射老是待在對應於關鍵字的哈希碼的哈希表元中)。」 「該特性對於實現高速緩存的「刪除最近最少使用」的原則頗有用。例如,你能夠但願將最常訪問的映射保存在內存中,而且從數據庫中讀取不常常訪問的對象。 當你在表中找不到某個映射,而且該表中的映射已經放得很是滿時,你可讓迭代器進入該表,將它枚舉的開頭幾個映射刪除掉。這些是最近最少使用的映射。」 (6) protected boolean removeEldestEntry(Map.Entry eldest): 若是你想刪除最老的映射,則覆蓋該方法,以便返回true。當某個映射已經添加給映像以後,便調用該方法。它的默認實現方法返回false,表示默認條件 下老的映射沒有被刪除。可是你能夠從新定義本方法,以便有選擇地在最老的映射符合某個條件,或者映像超過了某個大小時,返回true。
4.6. WeakHashMap類 WeakHashMap是Map的一個特殊實現,它使用WeakReference(弱引用)來存放哈希表關鍵字。使用這種方式時,當映射的鍵在 WeakHashMap 的外部再也不被引用時,垃圾收集器會將它回收,但它將把到達該對象的弱引用歸入一個隊列。WeakHashMap的運行將按期檢查該隊列,以便找出新到達的 弱應用。當一個弱引用到達該隊列時,就表示關鍵字再也不被任何人使用,而且它已經被收集起來。而後WeakHashMap便刪除相關的映射。 (1) WeakHashMap(): 構建一個空弱哈希映像 (2) WeakHashMap(Map t): 構建一個弱哈希映像,而且添加映像t中全部映射 (3) WeakHashMap(int initialCapacity): 構建一個擁有特定容量的空的弱哈希映像 (4) WeakHashMap(int initialCapacity, float loadFactor): 構建一個擁有特定容量和加載因子的空的弱哈希映像

4.7. IdentityHashMap類 IdentityHashMap也是Map的一個特殊實現。在這個類中,關鍵字的哈希碼不該該由hashCode()方法來計算,而應該由 System.identityHashCode方法進行計算(即便已經從新定義了hashCode方法)。這是Object.hashCode根據對象 的內存地址來計算哈希碼時使用的方法。另外,爲了對各個對象進行比較,IdentityHashMap將使用==,而不使用equals方法。 換句話說,不一樣的關鍵字對象,即便它們的內容相同,也被視爲不一樣的對象。IdentityHashMap類能夠用於實現對象拓撲結構轉換 (topology-preserving object graph transformations)(好比實現對象的串行化或深度拷貝),在進行轉換時,須要一個「節點表」跟蹤那些已經處理過的對象的引用。即便碰巧有對 象相等,「節點表」也不該視其相等。另外一個應用是維護代理對象。好比,調試工具但願在程序調試期間維護每一個對象的一個代理對象。 「IdentityHashMap類不是通常意義的Map實現!它的實現有意的違背了Map接口要求經過equals方法比較對象的約定。這個類僅使用在不多發生的須要強調等同性語義的狀況。」 (1) IdentityHashMap (): 構建一個空的全同哈希映像,默認預期最大尺寸爲21 「預期最大尺寸是映像指望把持的鍵/值映射的最大數目」 (2) IdentityHashMap (Map m): 構建一個全同哈希映像,而且添加映像m中全部映射 (3) IdentityHashMap (int expectedMaxSize): 構建一個擁有預期最大尺寸的空的全同哈希映像。放置超過預期最大尺寸的鍵/值映射時,將引發內部數據結構的增加,有時可能很費時 。


一部分做業:

★    1 有這樣一個LIST:{「1」, 「4」, 「4」, 「2」, 「5」, 「4」, 「7」,」5」},刪除裏面全部的」4」和」2」,而且把「5」改成「9」。(考察:LIST的刪除、遍歷  預計時間;40分鐘)
package demo2jihe;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class tets0ne {
    public static void main(String[] args) throws Exception {
        List list = new ArrayList();
        list.add("1");
        list.add("4");
        list.add("4");

        list.add("2");
        list.add("5");
        list.add("4");

        list.add("7");
        list.add("5");
        System.out.println(list);

        Iterator itr = list.iterator();
        while (itr.hasNext()) {
            String obj = (String) itr.next();
            // System.out.println(obj);

            if (obj.equals("4") || obj.equals("2"))
                itr.remove();
            /*
             * 注意:在迭代器中要刪除某個元素, 必須用迭代器的方法刪除,不能夠用list的方法
             */
        }
        for (int j = 0; j < list.size(); j++) {
            if("5".equals(list.get(j))){
                list.remove(j);
                list.add(j, "9");
            }
        }
        System.out.println(list);
    }
}
[1, 4, 4, 2, 5, 4, 7, 5]
[1, 9, 7, 9]
2.從控制檯循環輸入賬戶信息,以逗號隔開:」帳號,姓名,金額,性別」,CHECK正確後封裝爲對象加入LIST,當控制檯輸入「END」輸入截止。
步驟:
1.1 從控制檯輸入帳戶信息
1.2 判斷輸入內容是不是」END」。若是是則進入步驟5
1.3將賬戶信息加入LIST
1.4 驗證失敗,從新轉入步驟1
1.5遍歷這個list打印全部賬單信息

  3把全部CHECK出錯信息定義在一個名爲MESSAGE.TXT的文件中。格式:數據結構

  MSG1 = 帳號長度不夠。框架

  MSG2 = 帳號必須入力。dom

    ……編程語言

  要求輸入賬戶信息前把MESSAGE.TXT內容導入MAP,以後的CHECK出錯時從MAP取得提示信息。(考察:MAP基本操做  預估:80分鐘)

  4 創建一個MAP:{「1」->」A」, 「2」->」B」, 「3」->」C」, 「4」->」D」, 「5」->」F」},

  刪除鍵值爲偶數的映射,而且按照輸入順序將剩餘映射打印在控制檯。(考察:MAP刪除、遍歷  預估:40分鐘)


account.java
package oneTest;

public class Account {
    
    //帳號,姓名,金額,性別
    private String id;
    
    private String name;
    
    private double money;
    
    private String sex;
    
    
    public Account(String id,String name,double money,String sex){
        
        this.id = id;
        this.name = name;
        this.money = money;
        this.sex = sex;
        
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
    
}

two.java

package oneTest;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class Two {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        List list = new ArrayList();
        Map hm = new HashMap();
        try {
            
            BufferedReader br = new BufferedReader(new FileReader("message.txt"));
            String line;
            while( (line=br.readLine()) != null){
                
                String[] lineStr = line.split("=");
                hm.put(lineStr[0], lineStr[1]);
                
            }
            
            br.close();
            
            Account account;
            System.out.println("請輸入:帳號,姓名,金額,性別");
            br = new BufferedReader(new InputStreamReader(System.in));
            while( !(line=br.readLine()).equalsIgnoreCase("end")){
                
                String[] lineAcc = line.split(",");
                if(lineAcc.length == 4){
                    
                    try{
                        double money = Double.valueOf(lineAcc[2]);
                        account = new Account(lineAcc[0],lineAcc[1],money,lineAcc[3]);
                        list.add(account);
                    }catch(NumberFormatException nfe){
                        System.out.println(hm.get("MSG2"));
                        //continue;
                    }
                }else{
                    System.out.println(hm.get("MSG3"));
                }
                
            }
            
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch(IOException ioe){
            ioe.printStackTrace();
        }
        
        Iterator itr = list.iterator();
        while(itr.hasNext()){
            
            Account a = (Account)itr.next();
            System.out.println(a.getId() + "," + a.getName() + "," + a.getMoney() + "," + a.getSex());
            
        }

    }

}

message.txt

MSG1=帳號長度不夠。
MSG2=金額必須是數字。
MSG3=請按要求輸入。
請輸入:帳號,姓名,金額,性別
qwe,qwr,wqr,wq
金額必須是數字。
qwe,qwr,qw,end
金額必須是數字。
wmqwrm,qw,END
請按要求輸入。

請按要求輸入。
qwqwrqw,qwe,12,3r,we,
請按要求輸入。
相關文章
相關標籤/搜索