显式设置 ArrayList 的容量有什么好处
What is the benefit of setting the capacity of an ArrayList explicitly
在javaArrayList
中我们有一个构造函数-
ArrayList(int capacity)
和两个方法 -
void ensureCapacity(int minCapacity)
void trimToSize()
考虑一个代码示例:
ArrayList<String> arrayList3 = new ArrayList<>(5);
System.out.println(arrayList3.size());
arrayList3.add("Zebra");
arrayList3.add("Giraffe");
arrayList3.add("Bison");
System.out.println(arrayList3);
System.out.println(arrayList3.size());
arrayList3.add("Rhino");
arrayList3.add("Hippo");
arrayList3.add("Elephant");
arrayList3.add("Antelope");
System.out.println(arrayList3);
System.out.println(arrayList3.size());
输出:
0
[Zebra, Giraffe, Bison]
3
[Zebra, Giraffe, Bison, Rhino, Hippo, Elephant, Antelope]
7
在这里,我看不出设置初始容量如何影响程序的执行。 ArrayList
是一个灵活的列表,可以根据需要更改大小。那么显式设置容量有什么意义呢?
如果我想明确设置容量,有没有什么方法可以查看当前容量?由于int size()
显然不适用于此处。
ArrayList
作为 Dynamic array 数据结构的实现。
它会在其底层数组变满时调整大小(即当前列表索引超过底层数组的最后一个有效索引)。
发生这种情况时,方法 add()
(或 addAll
)将在内部调用方法 grow()
。这将使容量翻倍。 IE。它将创建一个 新数组,其中 length
比之前的 length
大两倍,外加一些 新元素 不适合当前尺寸。
增长的成本为O(n),因为所有先前添加的元素都需要复制到新数组。
提示:当不需要调整大小时,将在恒定时间内添加一个新元素 O(1).
No-argument constructor 创建容量为 10
.
的 ArrayList
如果您希望新创建的 ArrayList
最终包含比方说 50,000
元素,那么使用 重载构造函数 来提供50,000
的初始容量,以便通过避免不必要的调整大小来提高性能。
此外,为此你可以使用 ensureCapacity()
方法,它可以在 ArrayList
class 中访问(而不是在 List
接口中,因为 capacity 不适用于没有数组支持的 LinkedList
。
is there any method to view the current capacity
不,没有。这就是所谓的encapsulation。 ArrayList
、StringBuilder
、HashMap
等由普通数组支持,但它们不允许直接与其底层数组进行交互。
但是如果你遇到数组最初增加大小然后大量元素被删除的情况,并且你想释放未占用的堆space,你可以使用方法trimToSize()
:
Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.
但要谨慎使用,因为它会导致循环增长和修剪,从而导致性能下降。
注意如果列表大小适中,不用担心未占用的数量space,或者,如果您不希望一次性删除 80%
的数据。 IE。即使列表很大,但它的 50%
个元素被删除,并且你在它上面应用 trimToSize()
,它会用下一个添加的元素恢复它以前的容量——这就是不断增长和收缩的场景表现不佳的列表。
作为一个可能的选项,如果您遇到 大部分数据 可以从列表中删除的情况,而不是使用 trimToSize()
,您可以过滤掉必须保留的元素,将它们放入新列表并取消引用前一个。
在javaArrayList
中我们有一个构造函数-
ArrayList(int capacity)
和两个方法 -
void ensureCapacity(int minCapacity)
void trimToSize()
考虑一个代码示例:
ArrayList<String> arrayList3 = new ArrayList<>(5);
System.out.println(arrayList3.size());
arrayList3.add("Zebra");
arrayList3.add("Giraffe");
arrayList3.add("Bison");
System.out.println(arrayList3);
System.out.println(arrayList3.size());
arrayList3.add("Rhino");
arrayList3.add("Hippo");
arrayList3.add("Elephant");
arrayList3.add("Antelope");
System.out.println(arrayList3);
System.out.println(arrayList3.size());
输出:
0
[Zebra, Giraffe, Bison]
3
[Zebra, Giraffe, Bison, Rhino, Hippo, Elephant, Antelope]
7
在这里,我看不出设置初始容量如何影响程序的执行。 ArrayList
是一个灵活的列表,可以根据需要更改大小。那么显式设置容量有什么意义呢?
如果我想明确设置容量,有没有什么方法可以查看当前容量?由于int size()
显然不适用于此处。
ArrayList
作为 Dynamic array 数据结构的实现。
它会在其底层数组变满时调整大小(即当前列表索引超过底层数组的最后一个有效索引)。
发生这种情况时,方法 add()
(或 addAll
)将在内部调用方法 grow()
。这将使容量翻倍。 IE。它将创建一个 新数组,其中 length
比之前的 length
大两倍,外加一些 新元素 不适合当前尺寸。
增长的成本为O(n),因为所有先前添加的元素都需要复制到新数组。
提示:当不需要调整大小时,将在恒定时间内添加一个新元素 O(1).
No-argument constructor 创建容量为 10
.
ArrayList
如果您希望新创建的 ArrayList
最终包含比方说 50,000
元素,那么使用 重载构造函数 来提供50,000
的初始容量,以便通过避免不必要的调整大小来提高性能。
此外,为此你可以使用 ensureCapacity()
方法,它可以在 ArrayList
class 中访问(而不是在 List
接口中,因为 capacity 不适用于没有数组支持的 LinkedList
。
is there any method to view the current capacity
不,没有。这就是所谓的encapsulation。 ArrayList
、StringBuilder
、HashMap
等由普通数组支持,但它们不允许直接与其底层数组进行交互。
但是如果你遇到数组最初增加大小然后大量元素被删除的情况,并且你想释放未占用的堆space,你可以使用方法trimToSize()
:
Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.
但要谨慎使用,因为它会导致循环增长和修剪,从而导致性能下降。
注意如果列表大小适中,不用担心未占用的数量space,或者,如果您不希望一次性删除 80%
的数据。 IE。即使列表很大,但它的 50%
个元素被删除,并且你在它上面应用 trimToSize()
,它会用下一个添加的元素恢复它以前的容量——这就是不断增长和收缩的场景表现不佳的列表。
作为一个可能的选项,如果您遇到 大部分数据 可以从列表中删除的情况,而不是使用 trimToSize()
,您可以过滤掉必须保留的元素,将它们放入新列表并取消引用前一个。