我是一位经验丰富的Java开发人员,我一直在看这样的事情
List<Integer> l = new ArrayList<Integer>(0);
我真的无法理解。当你知道它会超出容量时,创建一个初始容量为0的ArrayList
有什么意义呢?
这样做有什么好处吗?
答案 0 :(得分:6)
对于java 6 (或openjdk 7),未指定初始大小会为您提供初始大小设置为 10 的列表。因此,根据您使用列表的许多因素,初始化大小为0
的列表可能会略微提高内存和/或性能。
对于java 7 ,指定初始大小0
在功能上等同于未指定初始大小。
然而它实际上效率较低,因为使用参数0
调用构造函数会调用new Object[0]
,而如果指定no-args构造函数,则初始elementData
对于您的列表,将设置为静态定义的名为EMPTY_ELEMENTDATA
的常量。
来自ArrayList
来源的相关代码:
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
换句话说,使用new ArrayList<Integer>(0);
似乎是多余的,这样做没有任何好处,我会改用new ArrayList<Integer>();
。
答案 1 :(得分:6)
它使ArrayList
的大小(在内存中)保持非常小,并且是您希望变量非空并且可以使用时的策略,但不要期望立即填充List
。如果您希望立即填充它,最好给它一个更大的初始值 - 任何&#34;成长&#34; ArrayList
的内部创建一个新的基本数组,并复制项目。 ArrayList
的增长是昂贵的,应该最小化。
或者,如果您正在创建批次类的实例,每个类都包含这些List
属性中的一个。如果你没有立即计划填写它们,你可以通过不分配房间来节省一些内存。
然而:有更好的方法:Collections.emptyList()
。通常,您希望直接保护对该列表的访问,并且(作为示例)您的类中提供对内部List
进行操作的特定于域的方法调用。例如,假设您有School
个班级,其中包含List
个学生姓名。 (保持简单。)
public class School {
private List<String> studentNames = Collections.emptyList();
public void addStudentName(String name) {
if (studentNames.isEmpty()) {
studentNames = new ArrayList<String>();
}
studentNames.add(name);
}
public void removeStudentName(String name) {
studentNames.remove(name);
if (studentNames.isEmpty()) {
studentNames = Collections.emptyList(); // GC will deallocate the old List
}
}
}
如果您愿意进行isEmpty()
检查并执行初始化/分配,这是创建大量空ArrayList
个实例的更好选择,因为Collections.emptyList()
是一个静态实例(只存在一个)并且不可修改。
答案 2 :(得分:3)
如果对ArrayList
的添加真的不太可能,并且将ArrayList
的大小保持在最低限度很重要,那么我可以看到它很有用。
或者,如果ArrayList
的唯一目的是从方法返回值,则返回空列表是函数调用者的特殊消息,如“找不到结果”。< / p>
否则,不是真的。
答案 3 :(得分:1)
向数组列表提供较大的值(如果列表将超出多少)总是更好的方法,因为它会减少列表的大小调整,从而优化执行时间。
使用值0
初始化数组列表创建Empty
数组列表,reducing memory
如果您知道列表的内容不会超过10
内容。
答案 4 :(得分:1)
默认情况下,ArrayList
的容量为10,每次调整幅度为+ 50%。
通过使用较低的初始容量,您可以有时(理论上)节省内存。另一方面,每次调整大小都很耗时。在大多数情况下,这只是先发制人优化的标志。
答案 5 :(得分:-2)
根据合同,您可以通过不使用空值来避免NullPointerExceptions。在某些情况下这是一种很好的做法,请参阅Joshua Bloch的Effective Java 第43项:返回空数组或集合,而不是空值