15.Java集合類

轉載請保留原文鏈接: http://dashidan.com/article/java/basic/15.html

15.Java集合類

Java集合類是java提供的工具包,包含了常用的數據結構:集合、鏈表、隊列、棧、映射等.Java集合類主要可以劃分爲4個部分:List列表、Set集合、Map映射、工具類(Iterator迭代器、Enumeration枚舉類、Arrays和Collections).

① 常用集合類接口

常用集合類繼承關係如下所示:

Collection
    |-List
        |-LinkedList
        |-ArrayList
        |-Vector
    |-Set
    |-HashSet
    |-Queue
Map
    |-Hashtable
    |-HashMap

1.Collection接口

Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements).由Collection接口派生的兩個接口是ListSet.List允許有相同元素, Set不允許有相同元素.

實現Collection接口的類都必須提供兩個標準的構造函數:

  • 無參數的構造函數用於創建一個空的Collection.

  • 有一個參數的構造函數用於創建一個新的Collection對象,這個對象傳入的Collection有相同的元素. 允許用戶複製一個Collection.

2.List接口

List有序Collection. 使用此接口能夠精確的控制每個元素插入的位置.能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組.

除了具有Collection接口必備的iterator()方法外, List還提供一個listIterator()方法, 返回一個ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向後遍歷.

實現List接口的常用類有LinkedList,ArrayList,VectorStack. 和Set不同, List允許有相同的元素.

3.Set接口

Set是一種不包含重複的元素的Collection,即任意的兩個元素e1e2都有e1.equals(e2)=false.

Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素.Set最多有一個null元素.

必須小心操作可變對象(Mutable Object)

如果一個`Set`中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題.

4.Queue接口

可以實現先進先出的隊列.LinkedList同樣實現了Queue接口.PriorityQueue用來創建自然排序的優先級隊列.

5.Map接口

Map提供keyvalue的映射. 一個Map中不能包含相同的key,每個key只能映射一個value.Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射.

`Map`沒有繼承`Collection`接口.

② 常用集合類

1.LinkedList

LinkedList實現了List接口,允許null元素.提供額外的get,remove,insert方法在LinkedList的首部或尾部.這些操作使LinkedList可被用作(stack),隊列(queue)或雙向隊列(deque).

`LinkedList`沒有同步方法

如果多個線程同時訪問一個List, 則必須自己實現訪問同步.

一種解決方法是在創建List時構造一個同步的List:

List list = Collections.synchronizedList(new LinkedList(...));.

2.ArrayList

ArrayList實現了變長數組.它允許所有元素,包括null.每個ArrayList實例都有一個容量(Capacity), 即用於存儲元素的數組的大小.這個容量可隨着不斷添加新元素而自動增加,但是增長算法並沒有定義.

當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率.
和LinkedList一樣,ArrayList也是非同步的(unsynchronized).

ArrayList添加刪除對象:

/** ArrayList添加對象*/ArrayList<Integer> intList = new ArrayList<>();System.out.println("ArrayList 長度: " + intList.size());for (int i = 0; i < 10; i++) {
    intList.add(i);}System.out.println("ArrayList 長度: " + intList.size());/** ArrayList刪除對象*/intList.remove(5);System.out.println("ArrayList 長度: " + intList.size());

ArrayList遍歷:

  • ArrayList 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引

for (Integer intNum : arrayList) {
    System.out.println(intNum);}
  • ArrayList 遍歷方式 2普通for循環, 索引和值都能獲得

for (int i = 0; i < arrayList.size(); i++) {
    int num = arrayList.get(i);
    System.out.println(num);}
  • ArrayList 遍歷方式 3 迭代器 Itertor, 無法獲得索引

Iterator<Integer> it = arrayList.iterator();while (it.hasNext()) {
    int num = it.next();
    System.out.println(num);}

3.Vector

Vector非常類似ArrayList,但Vector是線程同步的.

Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一接口,但由於Vector是線程同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出ConcurrentModificationException,因此必須捕獲該異常.

代碼示例:

/** Vector*/Vector<Integer> vector = new Vector<>();System.out.println("Vector 長度: " + vector.size());for (int i = 0; i < 5; i++) {
    vector.add(i);}System.out.println("Vector 長度: " + vector.size());/** Vectort 刪除對象*/vector.remove(3);System.out.println("Vector 長度: " + vector.size());/** Vectort 遍歷方式 1 增強for循環*/for (Integer intNum : vector) {
    System.out.println(intNum);}

Vector添加刪除對象和遍歷方式和ArrayList類似, 參考ArrayList的代碼實現.

4.Stack

Stack繼承自Vector,實現一個後進先出的堆棧. stack的常用方法:

  • push: 放入棧

  • pop: 出棧

  • peek:得到棧頂的元素

  • empty:測試堆棧是否爲空

  • search:檢測一個元素在堆棧中的位置

代碼示例:

/** Stack*/Stack<Integer> stack = new Stack<>();System.out.println("Stack 長度: " + stack.size());for (int i = 0; i < 5; i++) {
    /** 入棧*/
    stack.push(i);}System.out.println("Stack 長度: " + stack.size());/** Stack pop 出棧*/stack.pop();System.out.println("Stack 長度: " + stack.size());/** Stack peek 得到棧頂的元素*/int peekNum = stack.peek();System.out.println("Stack peekNum: " + peekNum);/** Stack search 檢測一個元素在堆棧中的位置*/int pos = stack.search(3);System.out.println("Stack search pos: " + pos);/** Stack 遍歷方式 1 增強for循環*/for (Integer anIntList : stack) {
    int num = anIntList;
    System.out.println(num);}

`Stack`遍歷方式和`ArrayList`類似, 參考`ArrayList`的代碼實現.

5.HashMap類

HashMap是最常用的Map,不是線程安全的.它根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度.遍歷時,取得數據的順序是完全隨機的.

由於鍵對象不可以重複, 所以HashMap最多隻允許一條記錄的鍵爲空(null),允許多條記錄的值爲空(null).

由於作爲key的對象將通過計算其散列函數來確定與之對應的value的位置, 因此任何作爲key的對象都必須實現hashCodeequals方法.

`hashCode`和`equals`方法繼承自根類`Object`.

用自定義的類當作key

按照`散列函數`的定義,如果兩個對象相同,即`obj1.equals(obj2)=true`,則它們的`hashCode`必須相同,但如果兩個對象不同,則它們的`hashCode``不一定不同`.

如果兩個不同對象的hashCode相同,這種現象稱爲`衝突`. 衝突會導致操作哈希表的時間開銷增大.

所以儘量定義好的`hashCode()`方法,能加快哈希表的操作.如果相同的對象有不同的`hashCode`,對哈希表的操作會出現意想不到的結果(`期待的get方法返回null`).

要避免這種問題,只需要牢記一條:要同時覆寫`equals`方法和`hashCode`方法, 而不要只寫其中一個.

代碼示例: HashMap添加和刪除對象:

HashMap<Integer, Integer> hashMap = new HashMap<>();System.out.println("HashMap 長度: " + hashMap.size());for (int i = 0; i < 5; i++) {
    /** HashMap 添加對象*/
    hashMap.put(i, 100 + i);}System.out.println("HashMap 長度: " + hashMap.size());/** HashMap 刪除對象*/hashMap.remove(2);System.out.println("HashMap 長度: " + hashMap.size());

HashMap遍歷:

  • HashMap 遍歷方式 1 增強for循環遍歷 Entry

推薦使用

直接拿到了key和value的對象, 省去了`get`數據的操作,效率最高.

System.out.println("HashMap 遍歷方式 1 增強for循環遍歷 Entry ");for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
    System.out.println("hashMap key: " + entry.getKey() + " hashMap value: " + entry.getValue());}
  • HashMap 遍歷方式 2 通過迭代器遍歷 key

Iterator<Integer> it0 = hashMap.keySet().iterator();while (it0.hasNext()) {
    int key = it0.next();
    int value = hashMap.get(key);
    System.out.println("key: " + key + " value: " + value);}
  • HashMap 遍歷方式 3 通過 增強for循環遍歷 key

for (Integer key : hashMap.keySet()) {
    int value = hashMap.get(key);
    System.out.println("key: " + key + " value: " + value);}
  • HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值

Iterator<Integer> it1 = hashMap.values().iterator();while (it1.hasNext()) {
    int value = it1.next();
    System.out.println("value: " + value);}
  • HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值

for (Integer value : hashMap.values()) {
    System.out.println("value: " + value);}

6.Hashtable

Hashtable繼承Map接口,實現一個key-value映射的哈希表. 任何非空(non-null)的對象都可作爲key或者value.
HashtableHashMap類似,是HashMap的線程安全版,是線程同步的,即任一時刻只有一個線程能寫Hashtable,因此也導致了Hashtale在寫入時會比較慢. 它繼承自Dictionary類,不同的是它不允許記錄的鍵或者值爲null,同時效率較低.

建議使用ConcurrentHashMap替代

如果需要線程同步的map, 建議使用線程同步的ConcurrentHashMap類. 不建議使用這個類, 並沒有示例代碼.

7.WeakHashMap

WeakHashMap是一種改進的HashMap. 它對key實行弱引用,如果一個key不再被外部所引用,那麼該key可以被Java的垃圾回收器(GC)回收.

使用方式同`HashMap`.

8. HashSet

HashSet中元素是無序的(這個無序指的是數據的添加順序和後來的排列順序不同),而且元素不可重複.

HashSet的底層是數組,在增加和刪除的時候由於運用的hashCode的比較來確定添加元素的位置,不存在元素的偏移, 因此查詢和刪除和增加元素的效率都非常高.

但是HashSet增刪的高效率是通過花費大量的空間換來的, 因爲空間越大,取餘數相同的情況就越小.HashSet這種算法會建立許多無用的空間.

使用HashSet類時如果發生衝突,就會出現遍歷整個數組的情況,這樣就使得效率非常的低.

/** 循環兩次,放入重複的1-5*/for (int i = 0; i < 5; i++) {
    hashSet.add(i);}for (int i = 0; i < 5; i++) {
    hashSet.add(i);}System.out.println("HashSet 長度: " + hashSet.size());/** HashSet 遍歷方式 1 增強for循環*/for (Integer intNum : hashSet) {
    System.out.println(intNum);}

由於HashSet去重功能, 第二次循環插入重複數據時, HashSet中並沒有加入新的數據, 長度依然是5. HashSet的遍歷方式同ArrayList,參考ArrayList的遍歷.

9.ConcurrentHashMap

線程同步的HashMap,線程安全並且鎖分離. ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的hash table,它們有自己的鎖. 只要多個修改操作發生在不同的段上,它們就可以併發進行.

使用方式同`HashMap`.

10.LinkedHashMap

有序的HashMap, 非線程安全. LinkedHashMap保存了記錄的插入順序,在用Iteraor遍歷LinkedHashMap時,先得到的記錄肯定是先插入的,在遍歷的時候會比HashMap慢,有HashMap的全部特性.

使用方式同`HashMap`.

11.TreeMap

TreeMap實現SortMap接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序(自然順序),也可以指定排序的比較器. 當用Iterator遍歷TreeMap時, 得到的記錄是排過序的.

TreeMap不允許key爲空,非線程同步.

使用方式同`HashMap`.

11.總結

  • 如果涉及到堆棧,隊列等操作,應該考慮用List. 對於需要快速插入,刪除元素,應該使用LinkedList, 如果需要快速隨機訪問元素,應該使用ArrayList.

  • 如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高.

  • 如果多個線程可能同時操作一個類,應該使用同步的類.

  • 要特別注意對哈希表的操作,作爲key的對象要正確覆寫equalshashCode方法.

  • 儘量返回接口而非實際的類型, 如返回List而非ArrayList, 這樣如果以後需要將ArrayList換成LinkedList時, 代碼接口不用改變.擴展性強.

③ 常用遍歷集合方式

1. 迭代器Iterator

不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代器,使用該迭代器即可逐一訪問Collection中每一個元素.典型的用法如下:

// 獲得一個迭代器Iterator it = collection.iterator();while(it.hasNext()) {
    //獲取下一個元素
    Object obj = it.next();}

2. foreach

增強for循環, JDK1.5之後提供的新功能, 可以輸出數組或集合.

3. for循環

普通for循環遍歷

示例代碼:

package com.dashidan.lesson13;import java.util.*;/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 13.Java集合類
 */public class Demo1 {
    public static void main(String[] args) {
        testArrayList();
        testVector();
        testStack();
        testHashMap();
        testHashSet();
    }

    /**
     * ArrayList基本操作
     */
    public static void testArrayList() {
        System.out.println("---ArrayList---");
        /** ArrayList添加對象*/
        ArrayList<Integer> arrayList = new ArrayList<>();
        System.out.println("ArrayList 長度: " + arrayList.size());
        for (int i = 0; i < 5; i++) {
            arrayList.add(i);
        }
        System.out.println("ArrayList 長度: " + arrayList.size());
        /** ArrayList刪除對象*/
        arrayList.remove(3);
        System.out.println("ArrayList 長度: " + arrayList.size());
        /** ArrayList 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引*/
        for (Integer intNum : arrayList) {
            System.out.println(intNum);
        }
        /** ArrayList 遍歷方式 2普通for循環, 值和索引都能得到*/
        for (int i = 0; i < arrayList.size(); i++) {
            int num = arrayList.get(i);
            System.out.println(num);
        }
        /** ArrayList 遍歷方式 3 迭代器 Itertor, 獲得值, 無法獲得索引*/
        Iterator<Integer> it = arrayList.iterator();
        while (it.hasNext()) {
            int num = it.next();
            System.out.println(num);
        }
    }
    /**
     * Vector基本操作
     */
    public static void testVector() {
        System.out.println("---Vector---");
        /** Vector*/
        Vector<Integer> vector = new Vector<>();
        System.out.println("Vector 長度: " + vector.size());
        for (int i = 0; i < 5; i++) {
            vector.add(i);
        }
        System.out.println("Vector 長度: " + vector.size());
        /** Vectort 刪除對象*/
        vector.remove(3);
        System.out.println("Vector 長度: " + vector.size());
        /** Vectort 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引*/
        for (Integer intNum : vector) {
            System.out.println(intNum);
        }
        /** Vectort 遍歷方式 2普通for循環, 值和索引都能得到*/
        for (int i = 0; i < vector.size(); i++) {
            int num = vector.get(i);
            System.out.println(num);
        }
        /** Vectort 遍歷方式 3 迭代器 Itertor, 獲得值, 無法獲得索引*/
        Iterator<Integer> it = vector.iterator();
        while (it.hasNext()) {
            int num = it.next();
            System.out.println(num);
        }
    }
    /**
     * Stack基本操作
     */
    public static void testStack() {
        System.out.println("---Stack---");
        /** Stack*/
        Stack<Integer> stack = new Stack<>();
        System.out.println("Stack 長度: " + stack.size());
        for (int i = 0; i < 5; i++) {
            /** 入棧*/
            stack.push(i);
        }
        System.out.println("Stack 長度: " + stack.size());
        /** Stack pop 出棧*/
        stack.pop();
        System.out.println("Stack 長度: " + stack.size());
        /** Stack peek 得到棧頂的元素*/
        int peekNum = stack.peek();
        System.out.println("Stack peekNum: " + peekNum);
        /** Stack search 檢測一個元素在堆棧中的位置*/
        int pos = stack.search(3);
        System.out.println("Stack search pos: " + pos);
        /** Stack 遍歷方式 1 增強for循環*/
        for (Integer intNum : stack) {
            System.out.println(intNum);
        }
    }
    /**
     * HashMap基本操作
     */
    public static void testHashMap() {
        System.out.println("---HashMap---");
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        System.out.println("HashMap 長度: " + hashMap.size());
        for (int i = 0; i < 5; i++) {
            /** HashMap 添加對象*/
            hashMap.put(i, 100 + i);
        }

        System.out.println("HashMap 長度: " + hashMap.size());
        /** HashMap 刪除對象*/
        hashMap.remove(2);
        System.out.println("HashMap 長度: " + hashMap.size());
        /** HashMap 遍歷方式 1 增強for循環遍歷 Entry */
        System.out.println("HashMap 遍歷方式 1 增強for循環遍歷 Entry ");
        for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
            System.out.println("hashMap key: " + entry.getKey() + " hashMap value: " + entry.getValue());
        }

        /** HashMap 遍歷方式 2 通過迭代器遍歷 key */
        System.out.println("HashMap 遍歷方式 2 通過迭代器遍歷 key *");
        Iterator<Integer> it0 = hashMap.keySet().iterator();
        while (it0.hasNext()) {
            int key = it0.next();
            int value = hashMap.get(key);
            System.out.println("key: " + key + " value: " + value);
        }

        /** HashMap 遍歷方式 3 通過 增強for循環遍歷 key*/
        System.out.println("HashMap 遍歷方式 3 通過 增強for循環遍歷 key");
        for (Integer key : hashMap.keySet()) {
            int value = hashMap.get(key);
            System.out.println("key: " + key + " value: " + value);
        }

        /** HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值 */
        System.out.println("HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值 ");
        Iterator<Integer> it1 = hashMap.values().iterator();
        while (it1.hasNext()) {
            int value = it1.next();
            System.out.println("value: " + value);
        }

        /** HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值 */
        System.out.println("HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值 ");
        for (Integer value : hashMap.values()) {
            System.out.println("value: " + value);
        }
    }

    /**
     * HashSet基本操作
     */
    public static void testHashSet() {
        System.out.println("---HashSet---");
        HashSet<Integer> hashSet = new HashSet<>();
        System.out.println("HashSet 長度: " + hashSet.size());
        /** 循環兩次,放入重複的1-5*/
        for (int i = 0; i < 5; i++) {
            hashSet.add(i);
        }
        for (int i = 0; i < 5; i++) {
            hashSet.add(i);
        }
        System.out.println("HashSet 長度: " + hashSet.size());
        /** HashSet 遍歷方式 1 增強for循環*/
        for (Integer intNum : hashSet) {
            System.out.println(intNum);
        }
    }}

輸出:

---ArrayList---
ArrayList 長度: 0
ArrayList 長度: 5
ArrayList 長度: 4
0
1
2
4
0
1
2
4
0
1
2
4
---Vector---
Vector 長度: 0
Vector 長度: 5
Vector 長度: 4
0
1
2
4
0
1
2
4
0
1
2
4
---Stack---
Stack 長度: 0
Stack 長度: 5
Stack 長度: 4
Stack peekNum: 3
Stack search pos: 1
0
1
2
3
---HashMap---
HashMap 長度: 0
HashMap 長度: 5
HashMap 長度: 4
HashMap 遍歷方式 1 增強for循環遍歷 Entry
hashMap key: 0 hashMap value: 100
hashMap key: 1 hashMap value: 101
hashMap key: 3 hashMap value: 103
hashMap key: 4 hashMap value: 104
HashMap 遍歷方式 2 通過迭代器遍歷 key *
key: 0 value: 100
key: 1 value: 101
key: 3 value: 103
key: 4 value: 104
HashMap 遍歷方式 3 通過 增強for循環遍歷 key
key: 0 value: 100
key: 1 value: 101
key: 3 value: 103
key: 4 value: 104
HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值
value: 100
value: 101
value: 103
value: 104
HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值
value: 100
value: 101
value: 103
value: 104
---HashSet---
HashSet 長度: 0
HashSet 長度: 5
0
1
2
3
4

④ FAQ

集合類相關常見問題

1.集合類和數組的區別

  • 數組(可以存儲基本數據類型)是用來存現對象的一種容器, 數組的長度固定, 適合在對象數量固定時使用.

  • 集合(只能存儲對象,對象類型可以不一樣)的長度可變,可在對象數量不固定時使用.

2.ArrayListLinkedList區別

  • ArrayListLinkedList在用法上沒有區別,但是在功能上還是有區別的. LinkedList經常用在增刪操作較多而查詢操作很少的情況下, 比如隊列和堆棧. ArrayList則相反.

  • ArrayList底層是Object數組,所以ArrayList具有數組的查詢速度快的優點以及增刪速度慢的缺點. 而在LinkedList的底層是一種雙向循環鏈表.在此鏈表上每一個數據節點都由三部分組成:前指針(指向前面的節點的位置),數據,後指針(指向後面的節點的位置).最後一個節點的後指針指向第一個節點的前指針,形成一個循環.雙向循環鏈表的查詢效率低但是增刪效率高.

  • 對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針.

  • 對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據.

ArrayList和LinkedList應用場景

若只對單條數據插入或刪除,ArrayList的速度優於LinkedList. 但若是批量隨機的插入刪除數據,LinkedList的速度大大優於ArrayList. 因爲ArrayList每插入一條數據,要移動插入點及之後的所有數據.

隊列和棧

隊列:先進先出的數據結構.

棧:後進先出的數據結構.

使用棧的時候, 不能提供非末尾元素出棧的方法.

3.HashTableHashMap區別

  • Hashtable是基於陳舊的Dictionary類的, HashMap是Java 1.2引入的Map接口的一個實現

  • Hashtable是線程安全的,也就是說是同步的, 而HashMap是線程序不安全的,不是同步的

  • HashMap·允許存在一個爲空(null)的key,多個爲空(null)的value`.

  • Hashtablekeyvalue都不允許爲空(null).

4.ArrayListVector區別

  • Vector是線程同步的,所以它也是線程安全的. 而Arraylist不是線程同步的. 如果不考慮到線程的安全因素,一般用Arraylist效率比較高.

  • 如果集合中的元素的數目大於目前集合數組的長度時, Vector增長率爲目前數組長度的100%, 而Arraylist增長率爲目前數組長度的50%. 在集合中使用數據量比較大的數據,用Vector有一定的優勢.

  • 如果查找一個指定位置的數據, VectorArraylist使用的時間是相同的,都是O(1), 這個時候使用VectorArraylist都可以.

5.ArrayListLinklist區別

  • ArrayListVector是採用數組方式存儲數據, 此數組元素數大於實際存儲的數據以便增加和插入元素, 都允許直接序號索引元素, 但是插入數據要設計到數組元素移動等內存操作, 所以索引數據快插入數據慢. Vector由於使用了synchronized方法(線程安全)所以性能上比ArrayList要差.

  • LinkedList使用雙向鏈表實現存儲, 按序號索引數據需要進行向前或向後遍歷, 但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快!

  • 如果移動一個指定位置的數據花費的時間爲O(n-i),n爲總長度, 這個時候就應該考慮到使用Linklist, 因爲它移動一個指定位置的數據所花費的時間爲O(1), 而查詢一個指定位置的數據時花費的時間爲O(i).

6.HashMapTreeMap區別

  • TreeMap實現SortedMap, 元素順序固定. HashMap沒有實現該接口.

  • HashMap通過hashcode對其內容進行快速查找, HashMap中元素的排列順序是不固定的, 而TreeMap中所有的元素都保持着某種固定的順序. 如果需要得到一個有序的結果應該使用TreeMap.

  • Map中插入、刪除和定位元素,HashMap是最好的選擇. 但如果要按自然順序或自定義順序遍歷鍵, 那麼TreeMap會更好.

  • 使用HashMap要求添加的鍵類明確定義了hashCode()equals()的實現. 這個TreeMap沒有調優選項, 因爲該樹總處於平衡狀態.

⑤ 相關文章

 Java從入門到精通目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章