Map、Set、List集合差異及聯繫詳解

前言:java

數組Array和集合的區別:數組

一、數組是大小固定的,而且同一個數組只能存放類型同樣的數據(基本類型/引用類型)安全

二、JAVA集合能夠存儲和操做數目不固定的一組數據。數據結構

三、若程序時不知道究竟須要多少對象,須要在空間不足時自動擴增容量,則須要使用容器類庫,array不適用。 多線程

注:使用相應的toArray()和Arrays.asList()方法能夠相互轉換。性能

集合:優化

集合類存放於Java.util包中。spa

集合類存放的都是對象的引用,而非對象自己,出於表達上的便利,咱們稱集合中的對象就是指集合中對象的引用。.net

集合類型主要有三種:set(集)、list(列表)、map(映射)。命令行

1、Collection接口

Collection是最基本的集合接口,一個Collection表明一組Object,即Collection的元素。Java SDK提供的類都是繼承自Collection的「子接口」如List和Set。

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

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

由Collection接口派生的兩個接口是List和Set。

2、Set

Set接口一樣是Collection接口的一個子接口,Set不包含重複的元素。

HashSet:使用hashmap的一個集的實現。雖然集定義成無序,但必須存在某種方法能高效地找到一個對象。使用一個hashmap對象實現集的存儲和檢索操做時在固定時間內實現的。

TreeSet:在集中以升序對對象排序的集的實現。這意味着從一個TreeSet對象得到第一個迭代器將按升序提供對象。TreeSet類使用了一個TreeMap。

爲優化hashset空間的使用,能夠調優初始容量和負載因子。TreeSet 不包含調優選項,由於樹老是平衡的,保證了插入、刪除、查詢的性能的高效。

當您要從集合中以有序的方式抽取元素時,TreeSet實現會有用處。爲了能順利進行,添加到TreeSet的元素必須是可排序的。 

import java.util.*;
public class SetExample {
      public static void main(String args[]) {
          Set set = new HashSet();
          set.add("Bernadine");
          set.add("Elizabeth");
          set.add("Gene");
          set.add("Elizabeth");
          set.add("Clara");
          System.out.println(set);

          Set sortedSet = new TreeSet(set);
          System.out.println(sortedSet);
      }
}
[Gene, Clara, Bernadine, Elizabeth]
[Bernadine, Clara, Elizabeth, Gene]

3、List

List接口繼承了Collection接口,定義一個容許重複項的有序集合。該接口不但可以對列表的一部分進行處理,還添加了面向位置的操做。

實際上有兩種list:一種是基本的ArrayList,其優勢在於隨機訪問元素,另外一種是更強大的LinkedList,它並非快速隨機訪問設計的,而是具備更通用的方法。

List : 次序是List最重要的特色:它保證維護元素特定的順序。

ArrayList : 由數組實現的List。容許對元素進行快速隨機訪問,可是向List中間插入與移除元素的速度很慢。

LinkedList : 對順序訪問進行了優化,向List中間插入與刪除的開銷並不大,隨機訪問則相對較慢。還具備下列方法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 這些方法 (沒有在任何接口或基類中定義過)使得LinkedList能夠看成堆棧、隊列和雙向隊列使用。

Vector:實現一個相似數組同樣的表,自動增長容量來容納你所需的元素。使用下標存儲和檢索對象就象在一個標準的數組中同樣。你也能夠用一個迭代器從一個Vector中檢索對象Vector是惟一的同步容器類!!

stack:這個類從vector派生而來,並增長了方法實現棧,一種後進先出的存儲結構。

List的用法示例:

package collection;

import java.util.*;

public class SetExample {
    public static void main(String[] args) {
        List linkedList = new LinkedList();
        for (int i = 0; i <= 5; i++) {
            linkedList.add("a"+i);
        }
        System.out.println(linkedList);
        linkedList.add(3,"a100");
        System.out.println(linkedList);
        linkedList.set(6,"a200");
        System.out.println(linkedList);
        System.out.println(linkedList.get(2));
        System.out.println(linkedList.indexOf("a3"));
        linkedList.remove(1);
        System.out.println(linkedList);
    }
}

4、list和set對比

Set子接口:無序,不容許重複,檢索元素效率低下,刪除和插入效率高,插入和刪除不會引發元素位置改變。
List子接口:有序,能夠有重複元素,和數組相似,List能夠動態增加,查找元素效率高,插入刪除元素效率低,由於會引發其餘元素位置改變。

Set和List具體子類:
    Set
     |————HashSet:以哈希表的形式存放元素,插入刪除速度很快。

    List
     |————ArrayList:動態數組
     |————LinkedList:鏈表、隊列、堆棧。

5、map

map接口不是Collection接口的繼承。

不重複的鍵到值的映射。

Map.Entry 接口

map的entrySet()方法返回一個實現map.entry接口的對象集合。集合中每一個對象都是底層map中一個特定的鍵值對。

HashMap 類和 TreeMap 類

在map中插入、刪除和定位元素,HashMap是最好的選擇。但若是您要按順序遍歷鍵,那麼TreeMap 會更好。根據集合大小,先把元素添加HashMap,再把這種映射轉換成一個用於有序鍵遍歷的TreeMap 可能更快。

爲了優化hashmap空間的使用,您能夠調優初始容量和負載因子。這個treeMap沒有調優選項,由於該樹總處於平衡狀態。

hashtable:實現一個映象,全部的鍵必須非空。爲了能高效的工做,定義鍵的類必須實現hashcode()方法和equal()方法。這個類時前面Java實現的一個繼承,而且一般能在實現映象的其它類中更好地使用。

hashmap:實現一個映象,運行存儲空對象,並且容許鍵是空(因爲鍵必須是惟一的,固然只能有一個空)。

WeakHashMap:若是有一個鍵對於一個對象而言再也不被引用,鍵將被捨棄,WeakHashMap在具備大量數據時使用。

TreeMap: 實現這樣一個映象,對象是按鍵升序排列的。

map的使用示例:

如下程序演示了具體map類的使用。該程序對自命令行傳遞的詞進行頻率計數。hashmap起初用於數據存儲。後來,映射被轉換爲TreeMap以顯示有序的鍵列列表。

package collection;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class MapExample {
    public static void main(String[] args) {
        String[] array = {"a","b","c","d","e"};
        Map map = new HashMap();
        Integer ONE = new Integer(1);
        for (int i=0, n=array.length; i<n; i++) {
            String key = array[i];
            int frequency = i+1;
            map.put(key, frequency);
        }
        System.out.println(map);
        Map sortedMap = new TreeMap(map);
        System.out.println(sortedMap);
        //hashmap的同步
        Map map1 = Collections.synchronizedMap(map);
        System.out.println(map1);
    }
}

結果:

6、解惑:

一、什麼是iterator

對集合的遍歷,遍歷的時候不建議修改集合。

二、Iterator與ListIterator有什麼區別?

Iterator:只能正向遍歷集合

ListIerator:繼承Iterator,能夠雙向列表遍歷

三、HashMap與HashTable有什麼區別?

HashMap容許空值做爲鍵或值,不一樣步的,迭代時採用的是快速失敗機制

HashTable不容許空值,同步的

注:有多線程的可能時,使用hashtable,反之使用hashmap。非線程安全的數據結構能帶來更好地性能。

若是未來有可能須要按順序獲取鍵值對,hashmap是更好地選擇,由於hashmap的一個子類LinkedHashMap。

若是多線程時使用hashmap,Collections.synchronizedMap()能夠代替,總的來講HashMap更靈活。

四、在Hashtable上下文中同步是什麼意思?

同步意味着在一個時間點只能有一個線程能夠改變哈希表,任何線程在執行hashtable的更新操做前須要獲取對象鎖,其它線程等待鎖的釋放。

五、爲何Vector不推薦使用?

使用時ArrayList優先於Vector,Vector是同步的,性能會低一些,若是迭代一個vector,還要加鎖,以免其餘線程同一時刻改變集合,加鎖效率更慢。

 

江疏影講Java@目錄

相關文章
相關標籤/搜索