在Java中从ArrayList中删除对象
如果满足条件,我需要从在Java中从ArrayList中删除对象,java,performance,memory-management,arraylist,Java,Performance,Memory Management,Arraylist,如果满足条件,我需要从ArrayList中删除一些对象,我想知道哪种方法更有效 情况是这样的:我有一个类,它包含一个ArrayList,其中包含一些其他对象。我必须迭代这个ArrayList,并删除满足特定条件的所有元素。 据我所知,我可以选择删除以下内容: 创建一个新的ArrayList,并添加不符合条件的元素。迭代后,将旧的arraylist交换到新的arraylist,而不使用元素 创建一个新的ArrayList,并添加满足条件的元素。迭代后,使用removeAll()方法传递ArrayL
ArrayList
中删除一些对象,我想知道哪种方法更有效
情况是这样的:我有一个类,它包含一个ArrayList
,其中包含一些其他对象。我必须迭代这个ArrayList
,并删除满足特定条件的所有元素。
据我所知,我可以选择删除以下内容:
ArrayList
,并添加不符合条件的元素。迭代后,将旧的arraylist交换到新的arraylist,而不使用元素ArrayList
,并添加满足条件的元素。迭代后,使用removeAll()
方法传递ArrayList
和要删除的对象是否有更有效的方法从
ArrayList
删除对象?另一种方法:迭代器有一个可选的remove()-方法,该方法是为ArrayList实现的。您可以在迭代时使用它
但我不知道哪种变体的性能最好,你应该测量一下
星蓝评论说,复杂度不好,这也是正确的(对于ReaveALL()也是如此),因为ArrayList必须复制所有元素,如果中间元素是添加或移除的元素。在这种情况下,LinkedList应该工作得更好。但是,由于我们都不知道您的实际用例,最好的方法是测量所有变体,以选择最佳解决方案?JDK的默认集合类应该包含所有支持此方法的creator迭代器。
您可以在遍历ArrayList时向后迭代并删除。这样做的优点是后续元素不需要移动,并且比向前移动更容易编程。首先,我要确保这确实是一个性能瓶颈,否则我会选择最干净、最具表现力的解决方案如果这是一个性能瓶颈,只需尝试不同的策略,看看什么是最快的。我的赌注是创建一个新的ArrayList并将所需的对象放入其中,丢弃旧的ArrayList。显然,在您提到的两种方法中,第1种更有效,因为它只需要遍历列表一次,而使用第2种方法,列表必须遍历两次(首先查找要删除的元素,然后单击它们以删除它们) 实际上,从另一个列表中删除元素列表可能是一种比O(n)更糟糕的算法,因此方法2更糟糕 迭代器方法:
List data = ...;
for (Iterator i = data.iterator(); i.hasNext(); ) {
Object element = i.next();
if (!(...)) {
i.remove();
}
}
我猜,最有效的方法是使用该方法并进行反向迭代:
for (ListIterator<E> iter = list.listIterator(list.size()); iter.hasPrevious();){
if (weWantToDelete(iter.previous())) iter.remove();
}
这可能是清理集合的最佳方法。由于它使用内部迭代,集合实现可以采用快捷方式使其尽可能快(对于
ArrayList
s,它可以将所需的复制量降至最低).除非你肯定你面临的问题确实是一个瓶颈,否则我会选择可读的
public ArrayList filterThings() {
ArrayList pileOfThings;
ArrayList filteredPileOfThings = new ArrayList();
for (Thing thingy : pileOfThings) {
if (thingy.property != 1) {
filteredPileOfThings.add(thingy);
}
}
return filteredPileOfThings;
}
我很赞成Mnementh的建议。
不过有一个警告
ConcurrentModificationException
请注意,您没有运行多个线程。如果执行多个线程,并且线程没有很好地同步,则可能会出现此异常。从ArrayList中删除元素会产生隐藏成本。每次删除元素时,都需要移动元素以填补“漏洞”。对于一个包含N个元素的列表,平均需要
N/2
个赋值
因此,从N元素数组列表中删除M个元素平均是O(M*N)
List data = ...;
List newData = new ArrayList(data.size());
for (Iterator i = data.iterator(); i.hasNext(); ) {
Object element = i.next();
if ((...)) {
newData.add(element);
}
}
如果N很大,我猜想对于小到3或4的M值,这种方法将比remove
方法更快
但是创建足够大的
newList
以容纳list
中的所有元素非常重要,以避免在扩展备份数组时复制备份数组。我找到了另一种更快的解决方案:
int j = 0;
for (Iterator i = list.listIterator(); i.hasNext(); ) {
j++;
if (campo.getNome().equals(key)) {
i.remove();
i = list.listIterator(j);
}
}
int-sizepuede=listaoptionVO.size();
对于(int i=0;i
编辑:使用迭代器添加缩进,您可以始终处理按顺序排列的元素,而不是指定的索引。因此,您不应该为上述问题而烦恼
Iterator itr = list.iterator();
String strElement = "";
while(itr.hasNext()){
strElement = (String)itr.next();
if(strElement.equals("2"))
{
itr.remove();
}
虽然这是违反直觉的,但我还是以这种方式大大加快了这项操作 正是我在做的:
ArrayList < HashMap < String , String >> results; // This has been filled with a whole bunch of results
ArrayList>results;//这里已经填充了一大堆结果
ArrayList ArrayList < HashMap < String, String>> results;
List < Integer > noIndex = getTheDiscardedIndexs(results);
for (int j = noIndex.size()-1; j >= 0; j-- ){
results.remove(noIndex.get(j).intValue());
}
ArrayList>结果;
ListnoIndex=getthediscardedindex(结果);
对于(int j=noIndex.size()-1;j>=0;j--){
results.remove(noIndex.get(j.intValue());
}
虽然GetTheDiscardedIndex保存的是一个索引数组,而不是一个HashMaps数组。事实证明,删除对象的速度要快得多(现在约为0.1秒),而且内存效率更高,因为我们不需要创建一个大的结果数组来删除
希望这对其他人有所帮助。但是
remove()
有一个警告:它可能不会删除您当前正在查看的对象。引用JavaDoc:更正式
ArrayList < HashMap < String , String >> results; // This has been filled with a whole bunch of results
ArrayList < HashMap < String, String>> results;
List < Integer > noIndex = getTheDiscardedIndexs(results);
for (int j = noIndex.size()-1; j >= 0; j-- ){
results.remove(noIndex.get(j).intValue());
}