在java中的给定索引处有效地在ArrayList中添加元素

时间:2013-06-17 11:10:29

标签: java performance arraylist

我需要在索引i

的ArrayList中插入Person类型的元素(我自己定义的类)

我知道我可以使用add(int index, E element)

但是有没有任何有效的方法可以做到这一点,因为在我的列表中平均花费大约1.5毫秒(收集的数据超过1000次,然后是平均值)。

3 个答案:

答案 0 :(得分:8)

如果您的任务更加强插入/删除,则可以始终使用java.util.LinkedList

  • ArrayList的大小有限。每次添加元素时,Java都会确保它适合 - 因此它会增加ArrayList。如果ArrayList增长得更快,就会发生大量的数组复制。
  • LinkedList只是将元素添加到正确的位置(链接周围的节点),而不会增长和复制整个ArrayList。
  • 当您搜索元素时,LinkedList的缺点是。由于它没有索引,因此必须从列表的开头到结尾遍历才能找到项目。

LinkedList

  • get is O(n)
  • add is O(1)
  • 删除是O(n)
  • Iterator.remove是O(1)

ArrayList

  • get is O(1)
  • add是O(1)摊销,但O(n)最坏情况,因为数组必须调整大小并复制
  • 删除是O(n)

答案 1 :(得分:0)

这种插​​入发生在O(n)中,因为它必须将所有元素向下移动,而在最坏情况下,它会将每个元素向下移动。 (更正了java说它是O(n),因为它们使用数学公式来插入)

如果你想快速插入,可以在arraylist的末尾添加它,或者使用一个恒定时间的hashmap。

插入hashmap: HashMap peopleMap = new Hashmap .....

peopleMap.put(person.name,person); //(或任何你想跟踪的内容)

这设置了人名和人的价值的关键。

您还可以尝试使用密钥(您想要跟踪的密码)的哈希映射,并为该人在持有者数组中的索引值。插入是O(i),查找O(i),你也可以对它进行排序(我将把它作为练习留给读者)

如果整个目的是排序,那么为了简单起见,你可以插入一个priorityQueue(nLogn),然后将所有内容弹出到数组中,这将为你提供一个排序数组

答案 2 :(得分:-1)

如果使用

添加
arryListInstance.add(positionIndex, Object);

在将现有对象筛选1个位置后添加对象。因此,该操作的平均情况变为 O(n)

虽然简单添加

arryListInstance.add(positionIndex, Object);

在arrayListInstance的末尾添加对象。在最好的情况下,此操作是 O(1),但在最坏的情况下,当达到最大容量时它变为 O(n):作为新的ArrayList实例是在内部创建,所有内容都在那里复制。

您正面临这个问题,因为可以避免第一个原因的两个原因之一:

  1. 您尚未为ArrayList对象定义足够的初始容量。因此,在每个 arrayListInstance.add(positionIndex,object)之前,使用增加的容量创建 new arrayListInstance ,然后复制原始列表中的现有元素,最后正在执行添加。如果您确切知道此列表要处理的数据量并相应地定义初始容量(与可能的元素数量相同),则可以避免这种情况。如果您无法预测初始容量,那么最好以 批次 处理数据。
  2. 在除最后一个位置之外的任何位置处的每次插入之后导致现有元素的筛选。这是不可避免的。因此,如果 positionIndex 不是arrayList的最后一个索引, arrayListInstance.add(positionIndex,object)将在 O(n)时执行。即使您使用 LinkedList ,也无法实现恒定时间添加操作,该操作会在除最后一个元素之外的索引处向列表中添加元素。