Vertor、HashTable、TreeMap、Set

Vertor

  1. 如果初始化不指定长度,长度默认为 10
  2. 初始化后,数组不为空,就设置好了长度和扩容增量,ArrayList 是第一次 add ,HashMap 第一次 put 才设置长度
  3. 如果创建实例时没有指定扩容增量,默认每次扩容后长度变为原来的 2 倍;如果指定了增量,每次扩容后,长度变为原来的长度+增量

构造方法

// 无参构造
public Vector() {
    this(10);
}

// 有参构造(参数是数组初始长度)
public Vector(int initialCapacity) {
	this(initialCapacity, 0);
}

// 有参构造(参数为数组初始长度、扩容增量)
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}

扩容

public synchronized boolean add(E e) {
    modCount++; // 修改数次+1
    ensureCapacityHelper(elementCount + 1); // 扩容,elementCount 是已保存的元素个数
    elementData[elementCount++] = e; // 元素放入扩容后的数组
    return true;
}

private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
    if (minCapacity - elementData.length > 0) // 如果原来的数组长度不够,就扩容
        grow(minCapacity); // 扩容
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length; // 原来的数组长度
    // 这里在判断扩容增量(创建实例的时候如果指定了就用它,如果没指定,就是原来的数组长度)然后再加上原来的数组长度
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity < 0) // 如果扩容后的长度不够,使用 minCapacity
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0) // Integer 最大值附近要专门处理,ArrayList 里见过了
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity); // 原来的数据拷贝到新的数组中
}

HashTable

  1. 原理 和 HashMap 基本一致,区别是 HashTable 是线程安全的,底层使用 synchronized 保证的

    public synchronized V put(K key, V value)
    
    public synchronized V remove(Object key)
    
    public synchronized void putAll(Map<? extends K, ? extends V> t)
    
    public synchronized void clear()
    
    ...
    
  2. 保证安全的代价太高了,把整个数组都锁住了,所以这个玩意已经不推荐使用了

TreeMap

底层是红黑树实现的,目前还不具备这方面的能力

Set

  1. 子类有 HashSet、TreeSet、LinkedHashSet

  2. 底层通过 Map 实现,每个实例都是先 new 一个 Map,每个操作都是变相的操作这个 Map,没有 Map 就没有 Set

    1. HashSet

      // HashSet 构造
      public HashSet() {
          map = new HashMap<>();
      }
      // HashSet 添加元素,就是保存 HashMap 的 key
      public boolean add(E e) {
          return map.put(e, PRESENT)==null;
      }
      
    2. LinkedHashSet

      public LinkedHashSet() {
          super(16, .75f, true);
      }
      
      // 内部 new 了一个 LinkedHashMap
      HashSet(int initialCapacity, float loadFactor, boolean dummy) {
          map = new LinkedHashMap<>(initialCapacity, loadFactor);
      }
      
    3. TreeSet

      public TreeSet() {
          this(new TreeMap<E,Object>());
      }
      
posted @ 2023-05-24 17:07  CyrusHuang  阅读(187)  评论(0编辑  收藏  举报