簡體   English   中英

從ArrayList中刪除多個元素

[英]Remove multiple elements from ArrayList

我有一堆索引,我想從ArrayList刪除這些索引中的元素。 我不能做一個簡單的remove()序列,因為每次刪除后都會移動元素。 我該如何解決這個問題?

要刪除indexes元素:

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

或者,使用Java 8中的Stream API:

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

按降序對索引進行排序,然后逐個刪除它們。 如果這樣做,刪除將無法影響您以后要刪除的任何索引。

如何對它們進行排序將取決於您用於存儲索引的集合。 如果是列表,您可以這樣做:

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

編輯

@aioobe找到了我找不到的助手。 而不是上述,你可以使用

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

我來這里是為了刪除特定范圍內的元素(即2個索引之間的所有元素),並發現:

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

您可以從最大索引向下刪除元素,或者如果您有對要刪除的對象的引用,則可以使用removeAll方法。

您可以按相反順序刪除索引。 如果索引的順序如1,2,3,則可以執行removeRange (1,3)。

我認為nanda是正確的答案。

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

masterList.removeAll(toRemove);

如果你有很多要刪除的元素(和一個長列表),迭代列表並將所有不被刪除的元素添加到新列表可能會更快,因為每個remove() step在一個數組中 -列表在逐個刪除之后復制所有元素。 在這種情況下,如果您的索引列表尚未排序(並且您可以與主列表並行迭代),您可能希望對包含使用HashSet或BitSet或類似的O(1)-access-structure contains()檢查:

/**
 * 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;
}

您可能希望將subList方法與要刪除的索引范圍一起使用,然后對其調用clear()。

(注意排除最后一個參數,只刪除第一個和第二個元素):

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);
}

}

結果將是:雞貓

如果要將位置X移除到大小

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

假設您的indexes數組已排序(例如:1,3,19,29),您可以這樣做:

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

一個更有效的方法,我想我上面沒有看到的是創建一個新的Arraylist並通過將它們復制到新數組來選擇哪些索引存活。 最后重新分配參考。

我最終在這里找到了類似的查詢,@ aioobe的回答幫助我找到了解決方案。 但是,如果要填充要自行刪除的索引列表,可能需要考慮使用

indices.add(0, i);

這將消除在迭代之前對列表進行(昂貴的)反向排序的需要,同時從主ArrayList中刪除元素。

訂購你的索引列表,就像這樣

如果2,12,9,7,3訂購desc到12,9,7,3,2

然后這樣做

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

這應該可以解決您的問題。

如果要刪除的元素全部組合在一起,則可以執行subList(start, end).clear()操作。

如果要刪除的元素是分散的,最好創建一個新的ArrayList,只添加要包含的元素,然后復制回原始列表。

編輯:我現在意識到這不是性能問題而是邏輯問題。

您可以對索引進行排序,或者您可以使用迭代器並調用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++;
    }

這取決於你需要什么,但在大多數情況下排序會更快

番石榴 你正在尋找的方法是Iterators.removeAll(Iterator removeFrom,Collection elementsToRemove)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM