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内容做了一些简单的总结。由于时间关系,真的很简单,觉得每个内容彻底说透,都是一个很漫长的过程。所以,本文只对这些容器做了初步的介绍和结构分析,便于初学者的初步了解,想要继续深刻,请看下回分解。。。。

相关文章
相关标签/搜索