2015-04-06 26 views
-1

給定一組職位,Set<Integer> positionsToRemove,我想從列表中刪除所有項目,List<?> list,它們的位置對應於集合中的值。如何從java列表中刪除項目 - 通過一組職位?

public static void remove(List<?> list, Set<Integer> positionsToRemove) { 
    // ? 
} 

注:

  • 列表可能會很長。
  • 該集可能很長。
  • 小心不要跌破IndexOutOfBounds或ConcurrentModificationException。
  • 您可以假定列表和集合不包含空值。
+0

做你的真的想修改你的原始列表,還是返回一個新的列表可接受? – 2015-04-06 08:54:43

+2

你嘗試了什麼? – 2015-04-06 08:55:27

+0

@LukasEder - 修改原始列表。 – 2015-04-06 08:55:59

回答

0
public static void remove(List<?> list, Set<Integer> positionsToRemove) { 
    for (Integer position : positionsToRemove) { 
     list.set((int)position, null); 
    } 
    for (Iterator<?> iterator = list.iterator(); iterator.hasNext();) { 
     Object o = iterator.next(); 
     if (o == null) iterator.remove(); 
    } 
} 
+0

這將刪除其他'null'值。 – 2015-04-06 08:53:21

+0

@BoristheSpider - 查看問題中的註釋。空值是不允許的。 – 2015-04-06 08:54:03

+0

您也可以使用Object marker = new Object();並將其用作刪除標記,如果允許nulls的話 – 2015-04-06 08:59:24

4

你必須確保在反向刪除項目,否則指數將失效。

您可以用List做到這一點很容易:

public static void remove(List<?> list, Set<Integer> positionsToRemove) { 
    final ListIterator<?> iter = list.listIterator(list.size()); 
    while (iter.hasPrevious()) { 
     iter.previous(); 
     if (positionsToRemove.contains(iter.nextIndex())) { 
      iter.remove(); 
     } 
    } 
} 

這需要的,如果ListIterator提供當前索引,也它在反向迭代能力的能力優勢。

它也不依賴於「標記值」,因此在輸入List中允許輸入null

很明顯,你可以做到這一點更簡單地用「舊式」索引循環:

public static void remove(List<?> list, Set<Integer> positionsToRemove) { 
    for (int i = list.size() - 1; i >= 0; --i) { 
     if (positionsToRemove.contains(i)) { 
      list.remove(i); 
     } 
    } 
} 

但要注意的是,如果List缺乏RandomAccess這將是O(n^2),而ListIterator基礎的解決辦法對於ListO(n)O(1)remove

可能更快地返回new List,取決於元素怎麼可能要刪除,也是List的類型 - 爲ArrayListremove操作是相當昂貴:

public static <T> List<T> remove(List<T> list, Set<Integer> positionsToRemove) { 
    return IntStream.range(0, list.size()) 
      .filter(i -> !positionsToRemove.contains(i)) 
      .mapToObj(list::get) 
      .collect(toList()); 
} 
0
public static void remove(List<?> list, Set<Integer> positionsToRemove) { 
    int i = 0; 
    for (Iterator<?> iterator = list.iterator(); iterator.hasNext(); ++i) { 
     iterator.next(); 
     if (positionsToRemove.contains(i)) iterator.remove(); 
    } 
} 
+0

該解決方案看起來比所有其他解決方案都要簡單。 – 2015-04-06 15:27:23

+0

垃圾!沒有注意到這是我的回答。 – 2015-04-06 15:37:40