對於Android開發者來說深入了解Java的集合類很有必要主要是從Collection和Map接口衍生出來的,目前主要提供了List、Set和 Map這三大類的集合
Collection接口主要有兩種子類分別為List和Set,區別主要是List保存的對象可以重復
而Set不可以重復
而Map一般為key-value這樣的對應關系,比如我們常用的HashMap。
數組
數組存儲區間是連續的,占用內存嚴重,故空間復雜的很大。但數組的二分查找時間復雜度小,為O(1);數組的特點是:尋址容易,插入和刪除困難;
鏈表
鏈表存儲區間離散,占用內存比較寬松,故空間復雜度很小,但時間復雜度很大,達O(N)。鏈表的特點是:尋址困難,插入和刪除容易。
哈希表
那么我們能不能綜合兩者的特性,做出一種尋址容易,插入刪除也容易的數據結構?答案是肯定的,這就是我們要提起的哈希表。哈希表((Hash table)既滿足了數據的查找方便,同時不占用太多的內容空間,使用也十分方便。
java中各種集合的關系圖
Collection 接口的接口 對象的集合
├ List 子接口 按進入先后有序保存 可重復
│├ LinkedList 接口實現類 鏈表 插入刪除 沒有同步 線程不安全
│├ ArrayList 接口實現類 數組 隨機訪問 沒有同步 線程不安全
│└ Vector 接口實現類 數組 同步 線程安全
│ └ Stack
└ Set 子接口 僅接收一次,並做內部排序
├ HashSet
│ └ LinkedHashSet
└ TreeSet
Collection 接口的接口 對象的集合
├ List 子接口 按進入先后有序保存 可重復
│├ LinkedList 接口實現類 鏈表 插入刪除 沒有同步 線程不安全
│├ ArrayList 接口實現類 數組 隨機訪問 沒有同步 線程不安全
│└ Vector 接口實現類 數組 同步 線程安全
│ └ Stack
└ Set 子接口 僅接收一次,並做內部排序
├ HashSet
│ └ LinkedHashSet
└ TreeSet
List 主要有ArrayList、LinkedList、Vector和Stack
一、List 主要有ArrayList、LinkedList、Vector和Stack
有關這些子類的性能,Android開發網從插入、刪除、移動等方面按照元素的執行效率做一一分析,通過分析Sun 的Java源碼和實際元素操作得出下面結論:
ArrayList -是線程不安全 底層是由數組實現 他的構造主要從AbstractList實現,主要是判斷下初始元素的容量,ArrayList最大的特點就是提供了Add、Get操作,當然可以通過迭代器來遍歷,對於元素的存在可以通過contains方法判斷。
有關這些子類的性能,Android開發網從插入、刪除、移動等方面按照元素的執行效率做一一分析,通過分析Sun 的Java源碼和實際元素操作得出下面結論:
ArrayList -是線程不安全 底層是由數組實現 他的構造主要從AbstractList實現,主要是判斷下初始元素的容量,ArrayList最大的特點就是提供了Add、Get操作,當然可以通過迭代器來遍歷,對於元素的存在可以通過contains方法判斷。
LinkedList - 線程不安全的 作為一種雙向鏈表結構,對於元素的插入、刪除效率比較高,只需要調整節點指向即可,但是對於隨機查找而言性能主要看這個鏈表長度和運氣了。 LinkedList也提供了ArrayList的get方法,但是要復雜的多,主要通過next或previous方法遍歷得到,LinkedList要移動指針。
Vector -線程安全的,這兩個類底層都是由數組實現的,效率低 比較簡單和ArrayList差不多,主要是內部實現了synchronized關鍵字,實現了線程安全訪問但性能有些降低,同時對於元素的擴充在算法上和ArrayList稍有不同,通過構造的容量增量系數來決定。
Stack - 作為棧的操作,本次繼承於Vector,提供了push,pop和peek方法,peek是不彈出根據數據大小獲取最后一個元素對象。
二、Set 主要有HashSet 和 TreeSet
HashSet - 該類是從Set接口繼承而來,相對於List而言就是說內部添加的元素不能重復, Hashtable 繼承 Map 接口,實現一個 key-value 映射的哈希表。任何非空( non-null )的對象都可作為 key 或者 value 。 當然從名字的Hash來看就是通過哈希算法來實現防止沖突來獲得防止重復的,整體上從HashMap實現,存放元素方法的也是類似key- value的對應的,通過迭代器遍歷,不過HashSet不是線程安全的。
HashSet - 該類是從Set接口繼承而來,相對於List而言就是說內部添加的元素不能重復, Hashtable 繼承 Map 接口,實現一個 key-value 映射的哈希表。任何非空( non-null )的對象都可作為 key 或者 value 。 當然從名字的Hash來看就是通過哈希算法來實現防止沖突來獲得防止重復的,整體上從HashMap實現,存放元素方法的也是類似key- value的對應的,通過迭代器遍歷,不過HashSet不是線程安全的。
TreeSet - 這個相對於HashSet而言主要是提供了排序支持,TreeSet是從TreeMap類實現,也是非線程安全的。
可以看到Set的兩個類都和Map有關,下面就一起看下有關映射(Map)相關的使用。
三、Map 主要有 HashMap 和 TreeMap
HashMap和Hashtable的區別
HashMap和Hashtable都實現了Map接口,但決定用哪一個之前先要弄清楚它們之間的分別。主要的區別有:線程安全性,同步(synchronization),以及速度。
- HashMap幾乎可以等價於Hashtable,除了HashMap是非synchronized的,並可以接受null(HashMap可以接受為null的鍵值(key)和值(value),而Hashtable則不行)。
- HashMap是非synchronized,而Hashtable是synchronized,這意味着Hashtable是線程安全的,多個線程可以共享一個Hashtable;而如果沒有正確的同步的話,多個線程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴展性更好。
- 另一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它線程改變了HashMap的結構(增加或者移除元素),將會拋出ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會拋出ConcurrentModificationException異常。但這並不是一個一定發生的行為,要看JVM。這條同樣也是Enumeration和Iterator的區別。
- 由於Hashtable是線程安全的也是synchronized,所以在單線程環境下它比HashMap要慢。如果你不需要同步,只需要單一線程,那么使用HashMap性能要好過Hashtable。
- HashMap不能保證隨着時間的推移Map中的元素次序是不變的。
HashMap - ,可以為空,提供了比較強大的功能實現,比如說loadFactor可以控制元素增長時內存分配,HashMap也是非線程安全的。
原理: