JavaRush /Java 博客 /Random-ZH /new ArrayList(????) 如何以及在哪里初始化更好
Vovan
第 22 级

new ArrayList(????) 如何以及在哪里初始化更好

已在 Random-ZH 群组中发布
不使用集合框架 来编写代码将是疯狂的。这是 Java 的一个精彩部分,有许多巧妙的解决方案。更重要的是,与数组不同,您不必担心大小。ArrayList会不断增长,直到内存耗尽。开发人员不必担心初始大小和ArrayIndexOutOfBoundsException错误。但如果有条件监控内存量怎么办?在处理集合时我们可以有效地使用内存吗?
出现了一个标准问题:如何初始化列表?下面的代码将不起作用:它将导致编译错误: 局部变量名称可能尚未 初始化。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 等等。
如果有 100 个元素, JVM将需要多次创建新数组并将元素复制到其中。考虑到这一点,如果对所需的数组大小有一个假设,最好将初始容量设置为接近该大小。以下是一些行动指南:
  1. 仅在需要时创建集合,否则将其初始化为 null 或使用Collections.EMPTY_LIST
  2. 如果您知道所需的确切大小,请在集合构造函数中指定它。
  3. 如果您确定元素数量不会超过 10,请随意使用默认构造函数。
  4. 与创建零大小集合相关的风险是创建新数组和复制数据的频率可能会更高。您需要非常仔细地考虑使用大小为零的集合是否有很多好处
  5. 如果你在方法开始时初始化的集合太大并且想要减少它,可以使用trimToSize()方法。
当然,这些准则适用于使用基于数组的集合,而对于链表来说,这些准则都没有意义。事实上,这些问题不太可能成为程序的杀手,但如果有机会做得更好一点,为什么不使用它呢。您还有其他有用的提示吗?您是否找到了让事情变得更好的方法?或者这一切都是不必要的吗?你怎么认为?
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION