错误地猜测ArrayList容量与未使用值之间的权衡?

时间:2014-10-30 09:07:47

标签: java algorithm optimization arraylist

假设我必须读出数据,可以是1个对象(大部分时间)或多个对象(有些时候)。

如果我这样做:

List list = new ArrayList<Object>(1);
... loop over the loaded object(s) and add it/them to the list...

当从数据库中只加载一个对象时,这对我来说很有用。 但假设我不得不扩展我的初始列表的不太常见的情况,这将导致我失去操作。

我认为这对现实世界的影响不大,但我想知道如何计算以下内容:

假设我的数据的 X%是1个对象, Y%是多个对象的列表。有没有办法可以计算我的列表的理想初始容量,进行最少的操作(通过列表扩展,列表中已分配但未使用的字段)?

1 个答案:

答案 0 :(得分:2)

您将数据分成两组X(1个元素)和Y个(多个)。您优化了X组的代码,因为它是最常见的情况。

使用一个元素初始化ArrayList是个好主意,所以大部分时间都不会浪费任何内存。

但是如果Y组的成员具有较高的平均大小(以及较小的标准偏差),您仍然可以使用ensureCapacity(int cap)优化最坏情况。在第二次迭代中,您可以强制将ArrayList支持数组的大小调整为Y组的平均大小。

对于具有100个元素的Y组的成员,它将创建/复制数组12次,并且如果实现优化,则后备数组长度将为141而不是1个小数组副本,并且不会浪费内存。

此优化示例:

Iterator<Obj> it = // Get your iterator from your resource
ArrayList<Obj> result = new ArrayList<Obj>(1);
if(it.hasNext()) {
    result.add(it.next());
}
if(it.hasNext()) {
    result.ensureCapacity(100);// Avg size of the Y group
    while(it.hasNext()) {
        result.add(it.next());
    }
}

但除非它是一个性能关键功能,否则它不值得付出努力。因为要确保这个技巧能够优化速度和记忆,你必须分析Y组中大小的分布。

它与你的问题没有直接关系,但它包含很多关于ArrayList的有用评论:When to use LinkedList over ArrayList?

相关问题