关于Linklist、Arraylis、Hashmap、Hashset、Hashtable t的特点、区别以及其数据结构

  根据官方文档可知:

     LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。

     ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)

           

       再看看他们之间的不同:顾名思义,LinkedList是链接表,而ArraylList是数组表,由此进一步可知LinkedList的每一个数据都有自己的存储地址,而ArraylList的数据都放在同一个地址。 再根据链表和数组的特点可以知道LinkedlList和ArraylList在对数据的增、删、改、查的特点。简单说一下。实现“增、删”功能,LinkedlList效率更高;“改、查”ArrayList效率更高。因此我认为LinkLedList被创造出来就是为了频繁的插入、删除数据的,如果需要频繁遍历那就应该选ArrayList,但是在考虑线性安全的情况下,则选择用vector。


      接下来是它们的数据结构:

      ArrayList

      ArrayList内部数据结构其实就是数组,它总是至少等于列表的大小。

      一般来说如果没有指定容量,那么容量的默认值为10。

        public ArrayList() {
                this(10);
        
}


  1.    public void ensureCapacity(int minCapacity) {  
  2. modCount++;  
  3. int oldCapacity = elementData.length;  
  4. if (minCapacity > oldCapacity) {  
  5.     Object oldData[] = elementData;  
  6.     int newCapacity = (oldCapacity * 3)/2 + 1;  
  7.         if (newCapacity < minCapacity)  
  8.     newCapacity = minCapacity;  
  9.     elementData = (E[])new Object[newCapacity];  
  10.     System.arraycopy(oldData, 0, elementData, 0, size);  
  11. }  
  12.    }  

      ArrayList是通过System.arraycopy方法将底层Object进行复制来处理数组的增长。当ArrayList的容量不够时,将其扩充至当前容量的1.5倍,若还不够,将其扩充至需要的数量。


      LinkedList

      LinkedList是通过结点的链接实现链表的数据结构,同链表一样,向LinkedList中插入或删除元素的速度是很快的但随机访问就很慢了。LinkedList的一些方法也使得它可以作为堆栈、队列和双队列等。

    


Map下的Hashmap和Hash


HashMap

   Hashmap是Map接口的实现。此实现提供所有可选的映射操作,并允许使用null键和null值。

     Hashmap的实例有两个参数影响其性能:初始容量和加载因子容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。

    Hashmap实际上是一个数组和链表的结合(就是散列表)


以下是部分源码:

Java代码   收藏代码
  1. /** 
  2.  * The table, resized as necessary. Length MUST Always be a power of two. 
  3.  */  
  4.   
  5. transient Entry[] table;  
  6.    
  7. static class Entry<K,V> implements Map.Entry<K,V> {  
  8.     final K key;  
  9.     V value;  
  10.     Entry<K,V> next;  
  11.     final int hash;  
  12.     ……  
  13. }  

   HashMap底层是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。table数组的元素是Entry类型的。每个 Entry元素其实就是一个key-value对,并且它持有一个指向下一个 Entry元素的引用,这就说明table数组的每个Entry元素同时也作为某个Entry链表的首节点,指向了该链表的下一个Entry元素,这就是所谓的“链表散列”数据结构,即数组和链表的结合体。

 HashTable

     此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。

     Hashtale和Hashmap采用相同的存储机制,两者的实现基本相同,但也仅仅只是基本相同。不同的是:

    1.Hashmap是非线程安全的,Hashtable是线性安全的。

    2.Hashtable不允许null值的存在。


Set下的HashSet


18    public HashSet() {  
19    map = new HashMap<E,Object>();  
20    }  

   从上面部分代码可看出Hashset的数据结构其实就是集合


      此类实现Set 接口,由哈希表(实际上是一个HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null 元素。

    Hashset是基于Hashmap实现的,它的底层用Hashmap来保存所有的元素,其相关操作基本是直接调用Hashmap的相关方法来完成。因此Hashset的实现比较简单。

猜你喜欢

转载自blog.csdn.net/zzly08/article/details/70184538
今日推荐