Remove multiple elements from ArrayList

一曲冷凌霜 提交于 2019-12-17 22:44:48

问题


I have a bunch of indexes and I want to remove elements at these indexes from an ArrayList. I can't do a simple sequence of remove()s because the elements are shifted after each removal. How do I solve this?


回答1:


Sort the indices in descending order and then remove them one by one. If you do that, there's no way a remove will affect any indices that you later want to remove.

How you sort them will depend on the collection you are using to store the indices. If it's a list, you can do this:

List<Integer> indices;
Collections.sort(indices, new Comparator<Integer>() {
   public int compare(Integer a, Integer b) {
      //todo: handle null
      return b.compareTo(a);
   }
}

Edit

@aioobe found the helper that I failed to find. Instead of the above, you can use

Collections.sort(indices, Collections.reverseOrder());



回答2:


To remove elements at indexes:

Collections.sort(indexes, Collections.reverseOrder());
for (int i : indexes)
    strs.remove(i);

Or, using the Stream API from Java 8:

indexes.sort(Comparator.reverseOrder());
indexes.stream().mapToInt(i -> i).forEach(l::remove);



回答3:


I came here for removing elements in specific range (i.e., all elements between 2 indexes), and found this:

list.subList(indexStart, indexEnd).clear()



回答4:


You can remove the elements starting from the largest index downwards, or if you have references to the objects you wish to remove, you can use the removeAll method.




回答5:


You can remove the indexes in reverse order. If the indexes are in order like 1,2,3 you can do removeRange(1, 3).




回答6:


I think nanda was the correct answer.

List<T> toRemove = new LinkedList<T>();
for (T t : masterList) {
  if (t.shouldRemove()) {
    toRemove.add(t);
  }
}

masterList.removeAll(toRemove);



回答7:


If you have really many elements to remove (and a long list), it may be faster to iterate over the list and add all elements who are not to be removed to a new list, since each remove()-step in a array-list copies all elements after the removed one by one. In this case, if you index list is not already sorted (and you can iterate over it parallel to the main list), you may want to use a HashSet or BitSet or some similar O(1)-access-structure for the contains() check:

/**
 * creates a new List containing all elements of {@code original},
 * apart from those with an index in {@code indices}.
 * Neither the original list nor the indices collection is changed.
 * @return a new list containing only the remaining elements.
 */
public <X> List<X> removeElements(List<X> original, Collection<Integer> indices) {
    // wrap for faster access.
    indices = new HashSet<Integer>(indices);
    List<X> output = new ArrayList<X>();
    int len = original.size();
    for(int i = 0; i < len; i++) {
       if(!indices.contains(i)) {
           output.add(original.get(i));
       }
    }
    return output;
}



回答8:


order your list of indexes, like this

if 2,12,9,7,3 order desc to 12,9,7,3,2

and then do this

for(var i = 0; i < indexes.length; i++) { source_array.remove(indexes[0]); }

this should resolve your problem.




回答9:


If the elements you wish to remove are all grouped together, you can do a subList(start, end).clear() operation.

If the elements you wish to remove are scattered, it may be better to create a new ArrayList, add only the elements you wish to include, and then copy back into the original list.

Edit: I realize now this was not a question of performance but of logic.




回答10:


You can sort the indices as many said, or you can use an iterator and call remove()

List<String> list = new ArrayList<String>();
    list.add("0");
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    List<Integer> indexes = new ArrayList<Integer>();
    indexes.add(2);
    indexes.add(5);
    indexes.add(3);
    int cpt = 0;
    Iterator<String> it = list.iterator(); 
    while(it.hasNext()){
        it.next();
        if(indexes.contains(cpt)){
            it.remove();
        }
        cpt++;
    }

it depends what you need, but the sort will be faster in most cases




回答11:


Use guava! The method you are looking is Iterators.removeAll(Iterator removeFrom, Collection elementsToRemove)




回答12:


you might want to use the subList method with the range of index you would like to remove and then call clear() on it.

(pay attention that the last parameter is excluded and only the first and the second elements will be removed):

public static void main(String[] args) {
    // TODO Auto-generated method stub
    ArrayList<String> animals = new ArrayList<String>();
    animals.add("cow");
    animals.add("dog");
    animals.add("chicken");
    animals.add("cat");
    animals.subList(0, 2).clear();
    for(String s:animals)
        System.out.println(s);
}

}

the result will be: chicken cat




回答13:


If you want to remove positions X to the Size

//a is the ArrayList
a=(ArrayList)a.sublist(0,X-1);



回答14:


Assuming your indexes array is sorted (eg: 1, 3, 19, 29), you can do this:

for (int i = 0; i < indexes.size(); i++){
   originalArray.remove(indexes.get(i) - i);
}



回答15:


A more efficient method that I guess I have not seen above is creating a new Arraylist and selecting which indices survive by copying them to the new array. And finally reassign the reference.




回答16:


I ended up here for a similar query and @aioobe's answer helped me figure out the solution. However, if you are populating the list of indices to delete yourself, might want to consider using this:

indices.add(0, i);

This will eliminate the need for (the costly) reverse-sorting of the list before iterating over it, while removing elements from the main ArrayList.



来源:https://stackoverflow.com/questions/4950678/remove-multiple-elements-from-arraylist

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!