java容器結構簡單解析

        java爲開發者提供了一套複雜的容器類型,整體來講共包含三大類實用容器,分別爲List、Set和Map,固然還有一類Queue用得特別少,徹底能使用List代替,就再也不進行介紹。在詳細介紹以前,先來看一看他們的關係圖(摘自Thinking in java)。java

    

        初看時可能以爲很複雜,難以理解整幅圖,不過不要緊,能夠先閱讀下文,待理解了部分類的功能後再回過頭來看這幅圖,可能有不同的收穫。算法

        1.collection

        Collection做爲最重要最基礎的父類,他是一個接口,繼承自Iterable接口:數組

public interface Collection<E> extends Iterable<E>

        Iterable接口含有一個iterator方法用以返回一個Iterator迭代器函數

public interface Iterable<T> {
    Iterator<T> iterator();
}

        Iterator接口其中含有2個重要方法,用以遍歷序列。Collection實現Iterable後,只須要實現iterator方法,返回一個自定義hasNext函數和next函數的匿名內部類,就能經過這兩個函數迭代訪問Collection中的元素,很是方便。更多詳細介紹請查閱java迭代器的介紹。工具

boolean hasNext();
E next();

        2.List

    一個 List 是一個元素有序的、能夠重複能夠爲 null 的集合(有時候咱們也叫它「序列」)。this

    List繼承自Collection接口:spa

public interface List<E> extends Collection<E>

    List含有一些與「列表」有關的方法定義,例如:code

int size();
boolean isEmpty();
boolean contains(Object o);
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
int indexOf(Object o);

   等等,在其實現類裏,對這些方法有不一樣的實現。不同凡響的是,List含有一個listIterator,返回一個ListIterator。這個迭代器可不是普通的迭代器,它能正向也能反向迭代,充分利用了LIst的特色。對象

  • AbstractList

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

AbstractList是具體List類的一個抽象定義,繼承自AbstractCollection而且實現了List接口。爲何要繼承自AbstractCollection呢,咱們來看一看它的源碼:繼承

public abstract class AbstractCollection<E> implements Collection<E>

AbstractCollection實現了Collection而且對一些通用方法進行了實現,例如:

public boolean isEmpty() {
    return size() == 0;
}

對不一樣LIst實現類有不一樣行爲的方法則保持爲抽象方法:

public abstract int size();
public abstract Iterator<E> iterator();

如今回到AbstractList,它在AbstractCollection的基礎上,對List的通用方法進行了進一步非實現,而且對一些方法進行限制,若是具體類沒有重寫這些方法,將不能使用這些方法,例如:

public E set(int index, E element) {
    throw new UnsupportedOperationException();
}

其緣由是,某些方法如:asList()會返回一個實現了AbstractList的內部類,而該類是固定值,不容許改變元素,所以在調用這些方法時就會產生UnsupportedOperationException,給於警告。

讓咱們看看AbstractList的實現類,Vector已通過時棄用了,再也不介紹。

  • ArrayList/LinkedList

        ArrayList是最經常使用的List,它經過維護一個數組保存數據,對隨機訪問是O(1)的複雜度,可是同數組同樣,對於插入和刪除,它的須要O(n)的複雜度。

Object[] elementData;

        而與之相反,LinkedList採用鏈表形式實現了List,對隨機訪問是O(n)的複雜度,對於插入和刪除,它的須要O(1)的複雜度。

Node<E> first
Node<E> last;

    Node用以保存一個節點的數據,它是LinkedList的內部類:

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

        其實LinkedList是繼承自AbstractSequentialList,AbstractSequentialList繼承了AbstractList,它是針對鏈表式的List進一步實現了部分方法。

 

        3.Set

    在Java中使用Set,能夠方便地將須要的類型以集合類型保存在一個列表中。Set是一個不包含重複元素的 Collection。    

    同List同樣,Set也是繼承自Collection,定義了一些關於「集合」操做的方法。

public interface Set<E> extends Collection<E>
  •      AbstractSet

    AbstractSet繼承自AbstractCollection,而且實現了Set,包含了AbstractCollection中的部分實現,和Set中的獨有方法。

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>

    其實它就實現了3個方法:

public boolean equals(Object o)
public int hashCode()
public boolean removeAll(Collection<?> c)

    set中判斷元素是否重複,靠的就是equals和hashCode,其重要程度可想而知。

  • HashSet

        HashSet繼承了AbstractSet,實現了Set。

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

        對於 HashSet 而言,它是基於 HashMap 實現的,HashSet 底層採用 HashMap 來保存全部元素,所以 HashSet 的實現比較簡單。

private transient HashMap<E,Object> map;

        由於採用散列表的方法,HashSet對與查找是很是迅速的,而且由於其元素不能重複的特性,是用來進行元素查重的常用的工具。

  •  LinkedHashSet

        HashSet和LinkedHashSet都是接口Set的實現,二者都不能保存重複的數據。

     主要區別是HashSet不保證集合中元素的順序,即不能保證迭代的順序與插入的順序一致。而LinkedHashSet按照元素插入的順序進行迭代,即迭代輸出的順序與插入的順序保持一致。

  • TreeSet

        與HashSet是基於HashMap實現同樣,TreeSet一樣是基於TreeMap實現的。TreeMap是一個有序的二叉樹,那麼同理TreeSet一樣也是一個有序的,它的做用是提供有序的Set集合。

        TreeSet在繼承了AbstractSet的基礎上,實現了NavigableSet。

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable

    讓咱們看看NavigableSet是什麼:

public interface NavigableSet<E> extends SortedSet<E>

    看名字就能猜出,這是使TreeSet保持有序的關鍵緣由。

    SortedSet    繼承自Set接口。

public interface SortedSet<E> extends Set<E>

    本質上來講,NavigableSet提供了一套二叉樹的接口方法,TreeSet利用這些方法實現了二叉樹。從而保證了元素的有序性。

 

        4.Map

    Map 是一種把鍵和值作映射的集合,它的每個元素都包含一個鍵象和一個值。 Map沒有繼承於Collection接口 ,從Map集合中檢索元素時,只要給出鍵對象,就會返回對應的值對象。反之亦然。

public interface Map<K,V>

      咋一看,Map的方法不少和Collection類似:

int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();

        可是其返回值或參數卻不同。containsKey判斷是否包含某鍵,containsValue判斷是否包含某值;get經過key獲取value,put存放key和value,keySet返回key的集合,values返回value的集合,entrySet返回key,value組的集合。

  •         AbstractMap

        AbstractMap實現了Map的大部分功能。有所差別的則留給下級類。

public abstract class AbstractMap<K,V> implements Map<K,V>

        這裏我只介紹了3種繼承自AbstractMap的類,其餘的應用場景比較特殊,並不常見。Map實現類的方法是至關複雜的,不少方法可能都不常見,這裏只對其原理作簡單介紹。

  • HashMap

     HashMap實現了Map接口,繼承AbstractMap。

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable

    其實現方法也是經過散列表的方法,便於快速經過key查找value。在HashMap中,key-value老是會當作一個總體來處理,系統會根據hash算法來來計算key-value的存儲位置,咱們老是能夠經過key快速地存、取value。

  • LinkedHashMap

    LinkedHashMap 是HashMap的子類,它能夠實現對容器內Entry的存儲順序和對Entry的遍歷順序保持一致。

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>

       爲了實現這個功能,LinkedHashMap內部使用了一個Entry類型的雙向鏈表,用這個雙向鏈表記錄Entry的存儲順序。當須要對該Map進行遍歷的時候,其實是遍歷的是這個雙向鏈表。

    LinkedHashMap內部使用的LinkedHashMap.Entry類繼承自 Map.Ent ry類,在其基礎上增長了LinkedHashMap.Entry類型的兩個字段,用來引用該Entry在雙向鏈表中的前面的Entry對象和後面的Entry對象。

       它的內部會在 Map.Entry 類的基礎上,增長兩個Entry類型的引用:before,after。LinkedHashMap使用一個雙向連表,將其內部全部的Entry串起來。

  • TreeMap

        同TreeSet同樣,TreeMap也在內部保證了key-value插入的有序性。它繼承自AbstractMap,實現了一樣奇怪的NavigableMap。

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable

        來看一看源碼,NavigableMap繼承自SortedMap,定義了大量紅黑樹有關的方法,在TreeMap中,經過實現這些方法維護紅黑樹,實現其有序性。

public interface NavigableMap<K,V> extends SortedMap<K,V>

 

        5.總結

        以上內容對java的Collection內容做了一些簡單的總結。由於時間關係,真的很簡單,覺得每個內容徹底說透,都是一個很漫長的過程。所以,本文只對這些容器做了初步的介紹和結構分析,便於初學者的初步瞭解,想要繼續深刻,請看下回分解。。。。

相關文章
相關標籤/搜索