Java 谷歌番石榴库中newArrayList(E…元素)的好奇心
此代码是guava库的简单代码 为了便于阅读,我对原始代码进行了简化,请参见=>Java 谷歌番石榴库中newArrayList(E…元素)的好奇心,java,collections,guava,Java,Collections,Guava,此代码是guava库的简单代码 为了便于阅读,我对原始代码进行了简化,请参见=> //案例A 公共静态ArrayList newArrayList(E…元素){ int capacity=computeArrayListCapacity(elements.length); ArrayList=新的ArrayList(容量); Collections.addAll(列表、元素); 退货清单; } 静态int-computeArrayListCapacity(int-arraySize){ 长值=5
//案例A
公共静态ArrayList newArrayList(E…元素){
int capacity=computeArrayListCapacity(elements.length);
ArrayList=新的ArrayList(容量);
Collections.addAll(列表、元素);
退货清单;
}
静态int-computeArrayListCapacity(int-arraySize){
长值=5L+arraySize+(arraySize/10);
如果(值>整数.最大值){
返回Integer.MAX_值;
}
if(值<整数最小值){
返回Integer.MIN_值;
}
返回(int)值;
}
为什么将容量设置为5L+arraySize+(arraySize/10)
三种情况(A、B、C)有什么不同
//案例B
公共静态ArrayList newArrayList(E…元素){
ArrayList=新的ArrayList(elements.length);
Collections.addAll(列表、元素);
退货清单;
}
//案例C
公共静态ArrayList newArrayList(E…元素){
ArrayList=新建ArrayList();
Collections.addAll(列表、元素);
退货清单;
}
马蒂亚斯的评论没有什么可补充的:
当列表稍后增长时,情况A是最佳的,但不会太多:小于10%再加上5个元素。如果它永远不会长大,那你就是在浪费一些记忆。如果它增长得更多,就会发生一些调整,但总的来说,任何人都无能为力
案例B在不太可能的情况下是最优的,列表不会增长。但这是不可能的,因为通常可以使用ImmutableList
案例C首先分配一个包含10个元素的数组,然后可以在
集合中多次替换这些元素。IIUIC对元素发生两次。长度==16
(即10->15->22
,因为ArrayList的增长因子是1.5)。它创建了一个新的ArrayList,它有一点额外的容量。由于列表通常在具有动态计数的数据时使用,这样做的好处是添加下一个元素时,列表不需要昂贵的调整大小(案例b)。调整大小的代价很高,因为它是通过创建一个新的(更大的)数组并将所有现有元素复制到该新数组中来完成的。您对Integer.MIN_VALUE
的质疑有误导性,我建议将其删除(无论如何,这并不准确,因为saturatedCast
从来不会同时进行这两项测试。@maaartinus是的,我没有使用computeArrayListCapacity方法。它只是guava-Ints.java.This中的代码。你可以看到5L+arraySize+(arraySize/10)
有一个“任务:找出正确的行为,并记录它
”旁边的注释基本上意味着这个表达式没有经过严格的研究。它的意思是允许在列表中添加一些内容,而且很可能是经验的(随机的)。这里的5
用于小列表(长度length
大约为10,因为它们不会从length/10
中得到任何东西),对于大列表,length/10
(成百上千的length
,因为对他们来说,5算不了什么)。同意所有的观点。我还想补充一点,没有理由不使用arraySize>>3而不是除法来节省大约40个周期(或者可能排列>>4
,1/8和1/16都接近1/10)。
// Case A
public static <E> ArrayList<E> newArrayList(E... elements) {
int capacity = computeArrayListCapacity(elements.length);
ArrayList<E> list = new ArrayList<E>(capacity);
Collections.addAll(list, elements);
return list;
}
static int computeArrayListCapacity(int arraySize) {
long value = 5L + arraySize + (arraySize / 10);
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (value < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) value;
}
//Case B
public static <E> ArrayList<E> newArrayList(E... elements) {
ArrayList<E> list = new ArrayList<E>(elements.length);
Collections.addAll(list, elements);
return list;
}
//Case C
public static <E> ArrayList<E> newArrayList(E... elements) {
ArrayList<E> list = new ArrayList<E>();
Collections.addAll(list, elements);
return list;
}