什么更快,创建一个Set或从列表中删除?

时间:2014-04-04 20:41:16

标签: java list set

我已经有List<T>,可能包含也可能不包含重复项。我将基于使用它们的一些计算结果构建Set<String>,因为在某些情况下,两个不同的T可以生成相同的String

List<T>中的某些元素具有不良属性,因此我需要将其过滤掉。我这样过滤:

List<T> myList = myCoolListGetter();
Iterator<T> it = myList.iterator();
T curr;
while (it.hasNext()) {
    curr = it.next();
    if (curr.shouldNotBeInResult()) {
        myList.remove(curr);
    }
}

然后我将此List<T>传递给另一个执行我提到的计算的方法,将它们添加到Set<String>

我想也许我可以通过将结果中的元素插入Set<T>而不是从List<T>中删除它来节省一些时间。既然我已经在这里迭代了List<T>,并且不得不在以后构建Set<String>,那么我真的会通过这样做来节省时间吗?

3 个答案:

答案 0 :(得分:2)

IMO,如果您可以指定足够的初始容量,请创建新的List<T>,然后从现有List<T>中删除(请参阅 - public ArrayList(int initialCapacity),允许您指定ArrayList构造时的容量的构造函数。因为那时你只需要添加元素而不必重新调整容量。重新调整意味着创建一个新的后备阵列并将现有的元素复制到该新阵列。

另一方面,从列表中删除将需要将其余元素移到左侧。该操作不需要移动元素的唯一时间是当被移除的元素是最后一个元素时。

我说的原因 - 新的List<T>而不是Set<T>是因为与集合不同,列表不需要关心添加的元素是否重复。

答案 1 :(得分:1)

考虑使用Google Guava的filterPredicate

Collection<T> filtered = Collections2.filter(myCoolListGetter(),
    new Predicate<T>() {
      public boolean apply(T t) {
        return !t.shouldNotBeInResult();
      }
    });

Iterable <T> filtered = Iterables.filter(myCoolListGetter(),
    new Predicate<T>() {
      public boolean apply(T t) {
        return !t.shouldNotBeInResult();
      }
    });

返回的集合/迭代器将被延迟评估,如果迭代则返回O(n)。懒惰的评价非常方便。 Iterables.filter特别好,因为它只显示了原始Iterable(列表)的过滤视图。没有创建新的ArrayList,它只是遍历每个项目并调用apply

答案 2 :(得分:0)

可能。将内容插入HashSet是O(1),因为散列使重复检查非常快。所以添加n个东西只会是O(n),这就是一旦你的列表需要多长时间。