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

Java ArrayList、HashSet和HashMap中的内存重新分配问题,java,arraylist,hashmap,hashset,Java,Arraylist,Hashmap,Hashset,看了一些非官方的参考资料,想在此确认我的理解是正确的。假设我们不时添加新的(独特的)元素 ArrayList会重新分配内存,因为它的内存需要是连续的,当新插入的元素增加的内存超过某个阈值时,会重新分配更大的连续内存空间,现有的元素会移动到新分配的更大的连续内存空间 HashSet和HashMap没有这样的问题,因为它们的内存不需要是连续的 顺便说一句,如果有关于这些领域的好文章,也请参考 问候,, Lin如果您在Java 8(jre 1.8.071)中的ArrayList中签出add(ee)方法

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

  • ArrayList
    会重新分配内存,因为它的内存需要是连续的,当新插入的元素增加的内存超过某个阈值时,会重新分配更大的连续内存空间,现有的元素会移动到新分配的更大的连续内存空间
  • HashSet
    HashMap
    没有这样的问题,因为它们的内存不需要是连续的
  • 顺便说一句,如果有关于这些领域的好文章,也请参考

    问候,,
    Lin

    如果您在Java 8(jre 1.8.071)中的
    ArrayList
    中签出
    add(ee)
    方法的源代码,它将调用一个名为
    ensureCapacityInternal(int minCapacity)
    。i、 e每次将对象添加到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);
        }
    
    /**
    *增加容量,以确保它至少可以容纳
    *最小容量参数指定的元素数。
    *
    *@param minCapacity所需的最小容量
    */
    私人空间增长(单位容量){
    //有溢出意识的代码
    int oldCapacity=elementData.length;
    int newCapacity=oldCapacity+(oldCapacity>>1);
    if(新容量-最小容量<0)
    新容量=最小容量;
    if(新容量-最大阵列大小>0)
    新容量=大容量(最小容量);
    //minCapacity通常接近大小,因此这是一个胜利:
    elementData=Arrays.copyOf(elementData,newCapacity);
    }
    
    这将创建一个比初始数组大1.5倍的新数组,并将所有元素从旧数组复制到新数组。这证明了你的第一点

    回到第2点,对于
    HashMap
    ,它们是一种特殊类型的数组,包含键和值对。此阵列插槽称为存储桶。所以,添加到HashMap中的每个对象都应该正确地重写
    hashCode()
    equals()
    方法。调用
    put(K键,V值)
    方法时,它会通过计算传递的键
    hash(对象键)
    的散列来调用名为
    putVal(int-hash,K键,V值,boolean-onlyfabsent,boolean-execute)的方法。这个散列表示值对象应该去的bucket位置。因此,这里的数组仅指示对象所在的地址块。线程对此进行了更详细的解释。
    
    我希望这就是你想要的

    似乎证明了这一点。它表示:当哈希表中的条目数超过负载因子和当前容量的乘积时,哈希表将被重新格式化(即,重建内部数据结构),以便哈希表的条目数大约是当前容量的两倍buckets@LinMa我的评论中的引用是从HashMap的javadoc中摘录的。我在评论中的链接指向HashMap的文档。HashSet是使用HashMap实现的。你真的需要花一些时间仔细阅读。LinkedList就是这样一种数据结构。还有树集和树映射。但你想得太多了。不重新分配并不意味着它更快。地图和清单的用途完全不同。如果您需要列表,请使用列表。如果你需要一套,就用一套。如果你需要地图,请使用地图。除了非常特定的用例外,ArrayList比LinkedList更快(并且使用更少的内存)。感谢sbaitmangalkar提供这些详细信息,我只想澄清一下,对于
    HashMap
    HashSet
    ,因为不需要在连续内存空间中,所以不会发生元素重新分配,对吗?是的,不需要连续的内存位置,也不需要重新分配。但是,每当地图动态调整大小时,现有的条目就会被重新分配。我很高兴它对您有所帮助!!