Java ArrayList,HashSet和HashMap中的内存重新分配问题

时间:2016-11-10 06:37:47

标签: java arraylist hashmap hashset

看了一些非官方的参考文献,并想在此确认我的理解是正确的。假设我们不时添加新的(唯一)元素,

  1. ArrayList<T>将重新分配内存,因为它的内存需要连续,当新插入的元素的内存增长超过某个阈值时,将重新分配更大的连续内存空间,并且现有元素将被移动到这样的新分配更大的连续存储空间;
  2. HashSet<T>HashMap<T>没有这样的问题,因为它们的记忆不需要连续吗?
  3. 顺便说一句,如果这些方面的一些好文章,也可以参考。

    的问候, 林

1 个答案:

答案 0 :(得分:2)

如果你在Java 8(jre 1.8.0_71)中检查add(E e)ArrayList<>方法的源代码,它会调用一个名为ensureCapacityInternal(int minCapacity)的方法。每次将对象添加到ArrayList时都会调用此方法。此inturn调用一系列方法,最后如果ArrayList的大小较小以容纳新添加的元素,则调用名为grow(int minCapacity)的方法。此方法如下所示:

/**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    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);
    }

这将创建一个大小比初始大小多1.5倍的新数组,并将旧数组中的所有元素复制到新数组中。这证明了你的观点。 1。

回到你的观点。 2,在HashMap<K,V>的情况下,它们是一种特殊类型的数组,用于保存键和值对。此阵列插槽称为存储区。因此,您添加到HashMap中的每个对象都应该正确覆盖hashCode()equals()方法。当您调用put(K key, V value)方法时,它会通过计算您已经传递的键putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)的#hash来调用名为hash(Object key)的方法。此哈希表示值对象的存储桶位置。因此,此处的数组仅指示对象所在的地址块。This线程更详细地解释了它。 我希望这就是你要找的东西。