2015-04-06 27 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