首页 > 其他 > 详细

集合源码分析

时间:2020-07-22 01:06:05      阅读:89      评论:0      收藏:0      [点我收藏+]

集合源码解析

Collection

代表一组对象,JDK不提供该接口的直接实现类,它提供了两个特定的子接口:Set和List。

List

是有序的集合,用户可以通过索引访问元素。List允许重复值。素引从0开始。

List接口提供了一个特殊的送代器,允许元素的插入和替换,以及除了其他选代器接口的常规操作的双向访问。

ArrayList

每个ArrayList实例都有一个容量,是存储的元素的数组的大小。向Arraytist添加元素时,容量会自动增长。

    public ArrayList(int initialCapacity) {
      if (initialCapacity > 0) {
          this.elementData = new Object[initialCapacity];
      } else if (initialCapacity == 0) {
          this.elementData = EMPTY_ELEMENTDATA;
      } else {
          throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
      }
  }

基于可变长度数组的实现。可以存入任何值,包含null。

向指定索引添加元素时,会将当前数组自当前索引后的所有对象复制到索引加一的位置,将新元素放入到当前位置。

    public void add(int index, E element) {
      rangeCheckForAdd(index);
?
      ensureCapacityInternal(size + 1); // Increments modCount!!
      System.arraycopy(elementData, index, elementData, index + 1,
                        size - index);
      elementData[index] = element;
      size++;
  }

添加大量元素时会调用ensureCapacity操作增加ArrayList的容量,可以减少重新分配的数量。

    private void grow(int minCapacity) {
      // overflow-conscious code
      int oldCapacity = elementData.length;
      int newCapacity = oldCapacity + (oldCapacity >> 1);
      if (newCapacity - minCapacity < 0)
          newCapacity = minCapacity;
      if (newCapacity - MAX_ARRAY_SIZE > 0)
          newCapacity = hugeCapacity(minCapacity);
      // minCapacity is usually close to size, so this is a win:
      elementData = Arrays.copyOf(elementData, newCapacity);
  }

该方法是非同步的。

Vector

Vector实现了一个可增长的对象数组。可以通过索引访问元素。

    public Vector(int initialCapacity, int capacityIncrement) {
      super();
      if (initialCapacity < 0)
          throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
      this.elementData = new Object[initialCapacity];
      this.capacityIncrement = capacityIncrement;
  }

每个Vector尝试维护capacity和capacityIncrement来优化存储。当大量元素添加到Vector时,数组会以capacityIncrement的大小进行扩容。

    public Vector(int initialCapacity, int capacityIncrement) {
      super();
      if (initialCapacity < 0)
          throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
      this.elementData = new Object[initialCapacity];
      this.capacityIncrement = capacityIncrement;
  }
    private void grow(int minCapacity) {
      // overflow-conscious code
      int oldCapacity = elementData.length;
      int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                        capacityIncrement : oldCapacity);
      if (newCapacity - minCapacity < 0)
          newCapacity = minCapacity;
      if (newCapacity - MAX_ARRAY_SIZE > 0)
          newCapacity = hugeCapacity(minCapacity);
      elementData = Arrays.copyOf(elementData, newCapacity);
  }

与Array list不同,Vector是同步的。

    public synchronized boolean add(E e) {
      modCount++;
      ensureCapacityHelper(elementCount + 1);
      elementData[elementCount++] = e;
      return true;
  }

Linkedlist

Linkedlist是List和Deque的一种双向链表的实现方式。可以存入任何值,包含null。

操作索引会从接近指定的索引位置的头部或尾部遍历列表。

    Node<E> node(int index) {
      // assert isElementIndex(index);
?
      if (index < (size >> 1)) {
          Node<E> x = first;
          for (int i = 0; i < index; i++)
              x = x.next;
          return x;
      } else {
          Node<E> x = last;
          for (int i = size - 1; i > index; i--)
              x = x.prev;
          return x;
      }
  }
  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;
      }
  }    

该实现是非同步的。

防止对List的非同步的访问,在创建时最好同步化。

List list = Collections.synchronizedList(new LinkedList(...));

Set

不包含重复数据的集合。可以为null,但只能有一个 。

HashSet

底层通过hashmap实现。不保证元素的顺序(指插入顺序,基于hash值排序),可为null。

private transient HashMap<E,Object> map;
public HashSet() {
  map = new HashMap<>();
}

该实现是非同步的。

public boolean add(E e) {
  return map.put(e, PRESENT)==null;
}

LinkedHashSet

基于Hash和双向链表的实现方试。双向链表定义了集合的顺序就是元表插入的序。可以为null。

元素的顺序不会因为重复添加而改变。

该实现是非同步的。

TreeSet

基于TreeMap。

元素自然比较器排序(默认向上排序),或通过创建时提供的比较器比较序。

public TreeSet() {
  this(new TreeMap<E,Object>());
}
?
public TreeSet(Comparator<? super E> comparator) {
  this(new TreeMap<>(comparator));
}

该实现是非同步的。

Map

匹配键值对的对象,不能包含重复的值,每个键只能匹配一个值。

HashMap

基于Hash表的实现方式。键值对都可以为空。

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
              boolean evict) {
  Node<K,V>[] tab; Node<K,V> p; int n, i;
  if ((tab = table) == null || (n = tab.length) == 0)
      n = (tab = resize()).length;
  if ((p = tab[i = (n - 1) & hash]) == null)
      tab[i] = newNode(hash, key, value, null);
  else {
      Node<K,V> e; K k;
      if (p.hash == hash &&
          ((k = p.key) == key || (key != null && key.equals(k))))
          e = p;
      else if (p instanceof TreeNode)
          e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
      else {
          for (int binCount = 0; ; ++binCount) {
              if ((e = p.next) == null) {
                  p.next = newNode(hash, key, value, null);
                  if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                      treeifyBin(tab, hash);
                  break;
              }
              if (e.hash == hash &&
                  ((k = e.key) == key || (key != null && key.equals(k))))
                  break;
              p = e;
          }
      }
      if (e != null) { // existing mapping for key
          V oldValue = e.value;
          if (!onlyIfAbsent || oldValue == null)
              e.value = value;
          afterNodeAccess(e);
          return oldValue;
      }
  }
  ++modCount;
  if (++size > threshold)
      resize();
  afterNodeInsertion(evict);
  return null;
}
static class Node<K,V> implements Map.Entry<K,V> {
  final int hash;
  final K key;
  V value;
  Node<K,V> next;
?
  Node(int hash, K key, V value, Node<K,V> next) {
      this.hash = hash;
      this.key = key;
      this.value = value;
      this.next = next;
  }
?
  public final K getKey()       { return key; }
  public final V getValue()     { return value; }
  public final String toString() { return key + "=" + value; }
?
  public final int hashCode() {
      return Objects.hashCode(key) ^ Objects.hashCode(value);
  }
?
  public final V setValue(V newValue) {
      V oldValue = value;
      value = newValue;
      return oldValue;
  }
?
  public final boolean equals(Object o) {
      if (o == this)
          return true;
      if (o instanceof Map.Entry) {
          Map.Entry<?,?> e = (Map.Entry<?,?>)o;
          if (Objects.equals(key, e.getKey()) &&
              Objects.equals(value, e.getValue()))
              return true;
      }
      return false;
  }
}

该实现是非同步的。

HashTable

基于Hash表的实现方式。键值对都不可以为空。

该实现是同步的。

LinkedHashMap

基于Hash和双向链表的实现方试。双向链表定义了集合的顺序就是元表插入的序。可以为null。

元素的顺序不会因为重复添加而改变。

该实现是非同步的。

集合源码分析

原文:https://www.cnblogs.com/tobefan/p/13357744.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!