Java集合类及内部部分实现浅析

常用List集合: 
特性: 
    有顺序的,元素可以重复; 
    遍历:for,迭代; 
    排序:Comparable Comparator Collections.sort() 
ArrayList: 
    用数组实现的List; 
    特点:查询效率高,增删效率低 轻量级 线程不安全; 
    部分源码分析: 
    构造: 
   

Java代码  收藏代码

  1. private transient Object[] elementData;  

  2.   

  3. public ArrayList(int initialCapacity) {  

  4.     super();  

  5.     if (initialCapacity < 0)  

  6.         throw new IllegalArgumentException("Illegal Capacity: "+  

  7.                                            initialCapacity);  

  8.     this.elementData = new Object[initialCapacity];  

  9. }  

  10.   

  11. public ArrayList() {  

  12.     this(10);  

  13. }  


    这段源代码表示的是一个ArrayList的内部实现为一个Object数组,重载的两个构造方法,默认长度为10。 
    增加元素: 
   

Java代码  收藏代码

  1.  public boolean add(E e) {  

  2.     ensureCapacityInternal(size + 1);  // Increments modCount!!  

  3.     elementData[size++] = e;  

  4.     return true;  

  5. }  

  6.   

  7. public boolean addAll(Collection<? extends E> c) {  

  8.     Object[] a = c.toArray();  

  9.     int numNew = a.length;  

  10.     ensureCapacityInternal(size + numNew);  // Increments modCount  

  11.     System.arraycopy(a, 0, elementData, size, numNew);  

  12.     size += numNew;  

  13.     return numNew != 0;  

  14. }  


    添加对象的代码块,size表示数组长度。后一个为添加集合对象的代码块。 

    删除元素: 
   

Java代码  收藏代码

  1.  public E remove(int index) {  

  2.     rangeCheck(index);  

  3.   

  4.     modCount++;  

  5.     E oldValue = elementData(index);  

  6.   

  7.     int numMoved = size - index - 1;  

  8.     if (numMoved > 0)  

  9.         System.arraycopy(elementData, index+1, elementData, index,  

  10.                          numMoved);  

  11.     elementData[--size] = null// Let gc do its work  

  12.   

  13.     return oldValue;  

  14. }  


    首先检查下标是否越界,List删除后会自懂向前移动下标向前移动一位又是通过 System.arraycopy(elementData, index+1, elementData, index,numMoved);来实现。 

    那么ArrayList是怎么实现容量自增的呢? 
    ensureCapacityInternal(size+numNew)表示数组容量的自增函数,调用下面的函数: 
   

Java代码  收藏代码

  1.  private void grow(int minCapacity) {  

  2.     // overflow-conscious code  

  3.     int oldCapacity = elementData.length;  

  4.     int newCapacity = oldCapacity + (oldCapacity >> 1);  

  5.     if (newCapacity - minCapacity < 0)  

  6.         newCapacity = minCapacity;  

  7.     if (newCapacity - MAX_ARRAY_SIZE > 0)  

  8.         newCapacity = hugeCapacity(minCapacity);  

  9.     // minCapacity is usually close to size, so this is a win:  

  10.     elementData = Arrays.copyOf(elementData, newCapacity);  

  11. }  



LinkedList: 
    底层用双向循环链表实现的List; 
    特点:查询效率低,增删效率高; 
    构造: 
   

Java代码  收藏代码

  1. transient Node<E> first;  

  2. transient Node<E> last;  

  3. public LinkedList() {  

  4. }  

  5. public LinkedList(Collection<? extends E> c) {  

  6.     this();  

  7.     addAll(c);  

  8. }  


    对于定义来说没有数组,却有个Node对象来看看静态内部类Node的结构: 
   

Java代码  收藏代码

  1. private static class Node<E> {  

  2.     E item;  

  3.     Node<E> next;  

  4.     Node<E> prev;  

  5.   

  6.     Node(Node<E> prev, E element, Node<E> next) {  

  7.         this.item = element;  

  8.         this.next = next;  

  9.         this.prev = prev;  

  10.     }  

  11. }  


    双向链表结构更像是一群牵着手的孩子只知道前后是谁。 

    添加元素: 
   

Java代码  收藏代码

  1. void linkLast(E e) {  

  2.     final Node<E> l = last;  

  3.     final Node<E> newNode = new Node<>(l, e, null);  

  4.     last = newNode;  

  5.     if (l == null)  

  6.         first = newNode;  

  7.     else  

  8.         l.next = newNode;  

  9.     size++;  

  10.     modCount++;  

  11. }  


    就是一个Node持有另个一Node的引用,形成以个链条。 
    删除元素: 
   

Java代码  收藏代码

  1. E unlink(Node<E> x) {  

  2.    // assert x != null;  

  3.    final E element = x.item;  

  4.    final Node<E> next = x.next;  

  5.    final Node<E> prev = x.prev;  

  6.   

  7.    if (prev == null) {  

  8.        first = next;  

  9.    } else {  

  10.        prev.next = next;  

  11.        x.prev = null;  

  12.    }  

  13.   

  14.    if (next == null) {  

  15.        last = prev;  

  16.    } else {  

  17.        next.prev = prev;  

  18.        x.next = null;  

  19.    }  

  20.   

  21.    x.item = null;  

  22.    size--;  

  23.    modCount++;  

  24.    return element;  


    先找到元素再赋值为null,并接上前面的。 
Vector: 
    底层用数组实现List接口的另一个类; 
    特点:重量级,占据更多的系统开销,线程安全; 
    Vector与ArrayList基本上一致,最大的差别于在一些方法上使用了synchronized关键字,使其变成线程安全。 

---------------------------------------------------------------------------------- 

Set: 
    无顺序的,元素不可重复(值不相同); 
    遍历:迭代; 
    排序:SortedSet 
HashSet: 
    采用哈希算法来实现Set接口; 
    唯一性保证:重复对象equals方法返回为true; 
    重复对象hashCode方法返回相同的整数,不同对象hashCode尽量保证不同(提高效率); 
    构造: 
   

Java代码  收藏代码

  1. private transient HashMap<E,Object> map;  

  2. private static final Object PRESENT = new Object();  

  3.  public HashSet() {  

  4.     map = new HashMap<>();  

  5. }  


    实际上的HashSet内部的实现为一个HashMap(下面看看HashMap的组成)。 
    添加元素: 
   

Java代码  收藏代码

  1. public boolean add(E e) {  

  2.     return map.put(e, PRESENT)==null;  

  3. }  


    由源代码块可以看出HashSet添加一个元素时,添加的值为HashMap的Key值,而一个Object对象却为一个Value值。 

    删除元素: 
   

Java代码  收藏代码

  1. public boolean remove(Object o) {  

  2.     return map.remove(o)==PRESENT;  

  3. }  


    那么HashSet无序不重复的属性则来自于HashMap。 
TreeSet: 
    在元素添加的同时,进行排序。也要给出排序规则; 
    唯一性保证:根据排序规则,compareTo方法返回为0,就可以认定两个对象中有一个是重复对象。 
    结构: 
   

Java代码  收藏代码

  1. private transient NavigableMap<E,Object> m;  

  2. private static final Object PRESENT = new Object();  


---------------------------------------------------------------------------------- 

Map: 
    元素是键值对:key唯一不可重复,value可重复; 
    遍历:先迭代遍历key的集合,再根据key得到value; 
SortedMap:元素自动对key排序 
HashMap: 
    轻量级,线程不安全,允许key或者value是null; 
    构造: 
   

Java代码  收藏代码

  1. transient Entry[] table;  

  2.    public HashMap(int initialCapacity, float loadFactor) {  

  3.     if (initialCapacity < 0)  

  4.         throw new IllegalArgumentException("Illegal initial capacity: " +  

  5.                                            initialCapacity);  

  6.     if (initialCapacity > MAXIMUM_CAPACITY)  

  7.         initialCapacity = MAXIMUM_CAPACITY;  

  8.     if (loadFactor <= 0 || Float.isNaN(loadFactor))  

  9.         throw new IllegalArgumentException("Illegal load factor: " +  

  10.                                            loadFactor);  

  11.   

  12.     // Find a power of 2 >= initialCapacity  

  13.     int capacity = 1;  

  14.     while (capacity < initialCapacity)  

  15.         capacity <<= 1;  

  16.   

  17.     this.loadFactor = loadFactor;  

  18.     threshold = (int)(capacity * loadFactor);  

  19.     [color=red]table = new Entry[capacity];[/color]  

  20.     init();  

  21. }  


    从构造方法分可以看出其为一个Entry数组 
    Entry主要属性: 
   

Java代码  收藏代码

  1. final K key;  

  2.    V value;  

  3.    Entry<K,V> next;  


    该源码片段可以看出Entry以及key值一旦赋值就无法更改。 
    添加元素: 
   

Java代码  收藏代码

  1. public V put(K key, V value) {  

  2.   if (key == null)  

  3.       return putForNullKey(value);  

  4.   int hash = hash(key.hashCode());  

  5.   int i = indexFor(hash, table.length);  

  6.   for (Entry<K,V> e = table[i]; e != null; e = e.next) {  

  7.       Object k;  

  8.       if ([color=red]e.hash == hash && ((k = e.key) == key || key.equals(k)[/color])) {  

  9.           V oldValue = e.value;  

  10.           e.value = value;  

  11.           e.recordAccess(this);  

  12.           return oldValue;  

  13.       }  

  14.   }  

  15.   

  16.   modCount++;  

  17.   addEntry(hash, key, value, i);  

  18.   return null;  


    红色部分对于重复对象的比较,使用了key的hashcode,key指向的地址,以及其值是否相等。 
   容量自增: 
  

Java代码  收藏代码

  1. void resize(int newCapacity) {  

  2.      Entry[] oldTable = table;  

  3.      int oldCapacity = oldTable.length;  

  4.      if (oldCapacity == MAXIMUM_CAPACITY) {  

  5.          threshold = Integer.MAX_VALUE;  

  6.          return;  

  7.      }  

  8.   

  9.      Entry[] newTable = new Entry[newCapacity];  

  10.      transfer(newTable);  

  11.      table = newTable;  

  12.      threshold = (int)(newCapacity * loadFactor);  

  13.  }  



Hashtable: 
    重量级,线程安全,不允许key或者value是null; 
    从源码可以看出与HashMap很相识,这是Hashmap为其轻量级的实现。 
    大量带有实际操作性的方法都为synchronized修饰。 
Properties:Hashtable的子类,key和value都是String,同样为线程安全。 
  

Java代码  收藏代码

  1. public synchronized Object setProperty(String key, String value) {  

  2.      return put(key, value);  

  3.  }   


TreeMap: 
    集合是指一个对象可以容纳了多个对象(不是引用),这个集合对象主要用来管理维护一系列相似的对象。


你可能感兴趣的:(Java集合类及内部部分实现浅析)