Java 当我们删除元素时,ArrayList的容量会减少吗?
ArrayList的默认容量为10个对象。当大小超过10个对象时,ArrayList将在内部增加其容量。从ArrayList中删除对象时,容量是否会减少Java 当我们删除元素时,ArrayList的容量会减少吗?,java,collections,arraylist,Java,Collections,Arraylist,ArrayList的默认容量为10个对象。当大小超过10个对象时,ArrayList将在内部增加其容量。从ArrayList中删除对象时,容量是否会减少 如果ArrayList容量没有减少,是否会导致性能问题?它不会自动减少容量。从医生那里 public void trimToSize() 将此ArrayList实例的容量修剪为列表的当前大小。应用程序可以使用此操作最小化ArrayList实例的存储 在arraylist中有几种删除方法,我将使用按索引删除版本作为示例 public
如果ArrayList容量没有减少,是否会导致性能问题?它不会自动减少容量。从医生那里
public void trimToSize()
将此ArrayList实例的容量修剪为列表的当前大小。应用程序可以使用此操作最小化ArrayList实例的存储 在arraylist中有几种删除方法,我将使用按索引删除版本作为示例
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
需要注意的最重要的一点是,从未在elementData
中创建新数组,因此其大小不会更改,只复制元素
如果需要减少数组列表的容量(通常不会使用),请使用
trimToSize()
ArrayList提供了一个方法trimToSize(),该方法
“将此ArrayList实例的容量修剪为列表的当前大小。应用程序可以使用此操作最小化ArrayList实例的存储。”请参阅
如果任何其他方法以静默方式执行此操作,这将取决于JRE提供的实现。
当我们从ArrayList中删除对象时,容量是否会降低。
答案是否定的。如果你观察这个类的源代码,你就会得到答案。没有任何操作可以减少ArrayList的
remove()
方法的容量。据我所知,ArrayList的容量只是增加了,要减少它必须将一个数组复制到另一个数组
我试着用我自己的实验来回答你们的问题。您无法查找数组列表的当前容量,因此我正在运行垃圾收集器并检查可用内存
My results are:
Before: 125637904
After Aloc: 126959888 -1321984
After Insert: 126718560 241328
After Clear: 126958496 -239936
After trim: 126998432 -39936
After nullify: 126998400 32
这很奇怪,我无法解释。分配列表会减少可用内存。在列表中插入增加的可用内存(我没想到)清除列表减少的可用内存(???)再次修剪列表减少可用内存(似乎没有清除),并将列表指针设置为null应该可以让我们回到开始的位置,但事实并非如此
我的代码如下:
package metcarob.com.dev.rubbish;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest {
private static long outputMem(String pre, long last) {
Runtime.getRuntime().gc();
String pre2 = " " + pre;
System.out.print(pre2.substring(pre2.length()-20) + " ");
long tv = Runtime.getRuntime().freeMemory();
System.out.print(tv);
if (last!=0) {
System.out.print(" " + (last - tv));
}
System.out.println("");
return tv;
}
public static void main(String[] args) {
long lm = outputMem("Before:",0);
ArrayList<String> lis = new ArrayList<String>();
lis.ensureCapacity(10000);
lm = outputMem("After Aloc:", lm);
for (int c=0;c<10000;c++) {
lis.add(new String("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"));
};
lm = outputMem("After Insert:", lm);
lis.clear();
lm = outputMem("After Clear:", lm);
lis.trimToSize();
lm = outputMem("After trim:", lm);
lis = null;
lm = outputMem("After nullify:", lm);
}
}
package metcarob.com.dev.垃圾;
导入java.util.ArrayList;
导入java.util.List;
公共类ArrayListTest{
私有静态long outputMem(字符串前置、长尾){
Runtime.getRuntime().gc();
字符串pre2=“”+pre;
System.out.print(pre2.substring(pre2.length()-20)+”);
long tv=Runtime.getRuntime().freemory();
系统输出打印(电视);
如果(最后一个!=0){
System.out.print(“+(last-tv));
}
System.out.println(“”);
返回电视;
}
公共静态void main(字符串[]args){
长lm=输出mem(“之前:”,0);
ArrayList lis=新的ArrayList();
资产负债表(10000);
lm=输出mem(“在Aloc之后:,lm);
对于(int c=0;c您询问了性能影响。您必须澄清“降低”性能的含义。如果每次降低阵列时都必须调整阵列大小,则每次都会重新复制阵列。另一方面,如果容量保持不变,则会占用不必要的内存
这是您的用例决定了这将如何影响用户感知的性能。它们是否运行在内存不足的机器上?我们是否在谈论大型的、主要是静态的阵列?阵列是否一直在变化
Java实现仅在需要时更改底层数组。这有助于避免不必要的拷贝,而以牺牲内存大小为代价。但是,它们使您能够在必要时对其进行修剪
移除元素时,ArrayList
的容量是否会减少
否。这是一个实现细节,但是ArrayList
类的任何(标准)实现都没有在删除元素时自动减少列表的容量
如果ArrayList
容量没有减少,是否会导致性能问题
嗯,总的来说没有
首先,列表通常不会收缩。(大多数列表的生命周期相对较短。它们经过处理,通过追加构建,然后进行处理。移除列表元素相对不常见……尽管这取决于应用程序。)因此,大多数情况下,这个问题都是没有意义的
其次,除非ArrayList
的大小过大,否则列表末尾未使用的空间不会对性能产生显著影响。事实上,只有当垃圾收集器标记并复制列表时,才会直接影响任何内容。而且影响相对较小,因为区域beyondArrayList
的逻辑端始终清除为null
,以防止内存泄漏
值得注意的是,通过追加到初始空列表而创建的ArrayList
可能会有一个平均过大50%的备份数组。这是因为ArrayList
s扩展备份数组的内置策略是将其大小加倍。这使得append
成为一个摊销O(1)
操作
第三,delete
或类似操作无法“知道”列表接下来会发生什么,因此无法判断调整大小是否合适
如果您的应用程序确实需要,它可以在删除元素后调用trimToSize()
。但是,请注意:
调用trimToSize()
代价很高。ArrayList
实现将创建一个全新的备份数组(大小正好合适)并复制所有数组元素
下次将元素插入或附加到