登录
登录 注册新账号
注册
已有账号登录
云原生应用架构设计与开发实战efada
daf 阅读 240 次
6月9日发布

下载网盘链接:云原生应用架构设计与开发实战

ArrayList 的工作原理
​​ArrayList​​ has 是一个内部的普通数组,它充任数据存储。在大多数状况下,我们不指定列表确实切大小。但是内部数组必需有一些大小!它的确如此。 它的默许大小是 10 。

public static void main(String[] args) {
ArrayList<Car> cars = new ArrayList<>();
}
复制代码
首先,让我们看看添加新元素是什么样的。首要任务是检查

内部数组在内部数组中能否有足够的空间,

以及能否能够再放一个元素。假如有空间,则将新元素添加到列表的末尾。当我们说“到最后”时,我们并不是指数组中的最后一个位置(那会很奇异)。我们指的是最后一个当前元素之后的位置。它的索引将是 ​​cars.size()​​ 。我们的列表目前是空的 ( ​​cars.size() == 0​​ )。因而,新元素将被添加到位置 0。

ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
cars.add(ferrari);
复制代码
这很分明。假如我们在中间插入会发作什么,即在其他元素之间?

public static void main(String[] args) {
ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
Car bugatti = new Car("Bugatti Veyron");
Car lambo = new Car("Lamborghini Diablo");
Car ford = new Car("Ford Modneo");

cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);

cars.add(1, ford);// add ford to cell 1, which is already occupied
}
复制代码
同样,首先检查数组中能否有足够的空间。假如有足够的空间,则 元素向右挪动 ,从我们插入新元素的位置开端。我们在位置 1 插入。换句话说,从位置 3 的元素被复制到位置 4,元素 2 到位置 3,元素 1 到位置 2。

然后我们的新元素被插入到它的位置。前一个元素 (bugatti) 曾经从那里复制到一个新位置。

如今让我们看看假如没有中央能够将新元素插入到数组中,这个过程是如何发作的。

当然,首先要检查能否有足够的空间。假如没有足够的空间,则在内部创立一个新数组 ​​ArrayList​​ 其大小是旧数组的大小乘以 1.5 加 1 在我们的例子中,新数组的大小将为 16。一切当前元素将立刻复制到那里。

渣滓搜集器将删除旧数组,只保存扩展后的新数组。如今有一个新元素的空间。我们将它插入到已被占用的位置 3。如今开端熟习的程序。一切从索引 3 开端的元素都向右挪动一个位置,并且新元素被悄然添加。 插入完成!我们完成了插入。如今让我们谈谈删除项目。你会记得我们在处置数组时遇到了一个问题:删除元素会在数组中产生“洞”。 每次删除,我们都必需编写本人的代码来执行这个转变。

​​ArrayList​​ 遵照相同的准绳,但它曾经完成了这种机制。

最终我们得到了我们想要的:

​​lambo​​ 元素已被删除。这里我们从中间移除了一个元素。显然,从列表末尾删除一个元素更快,由于该元素被简单地删除而无需挪动一切其他元素。让我们再次讨论一下内部数组的维度以及它在内存中的排列方式。

扩展阵列需求一些资源。

因而,不要创立 ​​ArrayList​​ 假如您肯定它至少有 100 个元素,则运用默许大小。插入第 100 个元素时,内部数组必需扩展 6 次,并且每次都必需挪动一切元素。

从 10 个元素到 16 个元素
从 16 个元素到 25 个元素
从 25 到 38
从 38 到 58
从 58 到 88
从 88 到 133(即旧数组的大小乘以 1.5 加 1)
能够想象,这是相当消耗资源的。因而,假如您曾经晓得(以至大约)所需的项目数量,最好创立一个具有特定大小数组的列表:

ArrayList<Car> cars = new ArrayList<>(100);
复制代码
如今将一次性分配 100 个元素的数组的内存,使数组更高效(不需求扩展)。这种战略也有另一面。

当您从 中删除对象时 ​​ArrayList​​ ,内部数组的大小不会自动减小。

假定我们有一个 ​​ArrayList​​ 包含 88 个元素的完好内部数组:

当程序运转时,我们删除了 77 个元素,所以只剩下 11 个:

你曾经猜到问题出在哪里了吗?你明白了,内存运用效率低下!我们在这里只运用了 11 个位置,但我们为 88 个元素分配了内存。这比我们需求的多 8 倍! ​​ArrayList​​ 在这种状况下,我们能够运用该类的一种特殊办法来优化内存运用: ​​trimToSize()​​ 此办法将内部数组的长度“修剪”为当前存储在其中的元素数。

如今我们只分配了我们需求的内存!