出现了一个标准问题:如何初始化列表?下面的代码将不起作用:它将导致编译错误: 局部变量名称可能尚未 初始化。Java 规范要求所有局部变量(存在于堆栈中的变量)都使用适当的值进行初始化。您可以这样做:毫无疑问,列表必须被初始化。您可以在第一行创建列表,也可以做一些更聪明的事情并使用延迟 初始化,就像我们在 getAllNames()方法中所做的那样。在这种情况下,列表只会在必要时创建 - 如果不满足初始条件,列表将永远不会出现在堆上。这里我们来到了主要问题: 我们应该为列表设置什么大小?最好的选择是给他准确的尺寸。例如:在这种情况下,必须返回 n 个名称,因此会创建一个包含 n 个元素的集合。 然而, n的确切值并不总是已知。即使在给出的示例中,如果 n=1000并且只有 100 个可用名称怎么办?使用集合时,最流行的方法是调用默认构造函数。如果您查看 Java 源代码(版本 1.6),您会看到, 默认情况下会创建一个包含 10 个元素的列表。也就是说,当我们不打算在列表中存储超过 10 个元素时,我们可以安全地使用默认构造函数。如果您尝试添加第 11 个元素会发生什么?好吧,没什么不好...元素将被成功添加。看方法: 数组的大小是由 ensureCapacity方法控制的。 尺寸增加1.5倍。创建一个新数组并将元素移入其中。如果我们将大小设置为 10,则在第 11 个元素上:
public List
getAllNames() { List
names; if (/*необходимые условия выполнены*/) { names = new ArrayList
(); /*заполнение списка*/ } return names; }
List
names = null; List
names = new ArrayList
(); List
names = new ArrayList
(0); List
names = new ArrayList
(size);
public List
getTopNames (int n) { List
names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList
(n); /*заполнение списка*/ } return names; }
names = new ArrayList
();
/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; }
public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
- 大小更改为 10 * 3 / 2 + 1 = 16
- 下一次增加 = 16 * 3 / 2 + 1 = 25
- 下一次增加 = 25 * 3 / 2 + 1 = 39 等等。
- 仅在需要时创建集合,否则将其初始化为 null 或使用Collections.EMPTY_LIST。
- 如果您知道所需的确切大小,请在集合构造函数中指定它。
- 如果您确定元素数量不会超过 10,请随意使用默认构造函数。
- 与创建零大小集合相关的风险是创建新数组和复制数据的频率可能会更高。您需要非常仔细地考虑使用大小为零的集合是否有很多好处。
- 如果你在方法开始时初始化的集合太大并且想要减少它,可以使用trimToSize()方法。
GO TO FULL VERSION