从Java中删除ArrayList中的对象

Car*_*tor 32 java performance memory-management arraylist

ArrayList如果它们符合条件,我需要删除一些对象,我想知道哪种方式可以更有效.

这是情况:我有一个ArrayList包含一些其他对象的类.我必须迭代这个ArrayList并删除满足特定条件的所有元素.据我所知,这些将是我删除的选项:

  1. 创建一个新的ArrayList并添加不符合条件的元素.在迭代之后,从旧的arraylist交换到没有元素的新arraylist.

  2. 创建一个新的ArrayList并添加符合条件的元素.在迭代之后,使用removeAll()传递ArrayList包含要删除的对象的方法.

是否有更有效的方法从ArrayList?删除对象?

Ric*_*dOD 47

您可以向后迭代并在浏览ArrayList时删除.这具有后续元素不需要移位的优点,并且比向前移动更容易编程.


Mne*_*nth 16

另一种方式:Iterator有一个可选的remove()方法,它是为ArrayList实现的.您可以在迭代时使用它.

我不知道,哪种变体是最高效的,你应该测量它.

starblue评论说,复杂性并不好,而且这也是真的(对于removeAll()),因为ArrayList必须复制所有元素,如果在中间是添加或删除的元素.对于那种情况,LinkedList应该更好.但是,因为我们都不知道您的真实用例,所以最好的方法是测量所有变体,以选择最佳解决方案.

  • 这是我在javadoc中看到的Iterator的remove()方法:"从底层集合中删除迭代器返回的最后一个元素(可选操作).每次调用next时,只能调用一次此方法.如果在迭代正在进行的过程中修改基础集合而不是通过调用此方法,那么迭代器是未指定的." 我错过了什么? (3认同)
  • 这比问题中的两个提案更糟糕,因为它导致O(n²)运行时. (2认同)

gus*_*afc 12

我想,大多数表现都会使用该listIterator方法并进行反向迭代:

for (ListIterator<E> iter = list.listIterator(list.size()); iter.hasPrevious();){
    if (weWantToDelete(iter.previous()))  iter.remove();
}
Run Code Online (Sandbox Code Playgroud)

编辑:很久以后,人们可能还想添加Java 8方法,使用lambda或方法引用从列表(或任何集合!)中删除元素.在就地filter进行集合,如果你喜欢:

list.removeIf(e -> e.isBad() && e.shouldGoAway());
Run Code Online (Sandbox Code Playgroud)

这可能是清理集合的最佳方法.由于它使用内部迭代,因此集合实现可以采用快捷方式使其尽可能快(对于ArrayLists,它可以最小化所需的复制量).


Jes*_*per 5

显然,在你提到的两种方法中,数字1更有效率,因为它只需要遍历列表一次,而使用方法编号2,列表必须遍历两次(首先找到要删除的元素,然后它们到删除它们).

实际上,从另一个列表中删除元素列表可能是一个比O(n)更差的算法,因此方法2更糟糕.

迭代器方法:

List data = ...;

for (Iterator i = data.iterator(); i.hasNext(); ) {
    Object element = i.next();

    if (!(...)) {
        i.remove();
    }
}
Run Code Online (Sandbox Code Playgroud)