Java Set - 哪个更快Set.add()或Set.addAll()?

时间:2015-09-26 16:41:06

标签: java collections set

Set维护唯一记录并在尝试复制现有元素时更新现有记录。

考虑以下两种情况。您认为两者之间的代码会更快更有效吗?

场景1:使用addAll()

Set<String> uniqueSet = new HashSet<String>();
uniqueSet = getSomedata(param1);
uniqueSet.addAll( getSomedata(param2) );

这里getSomedata()只返回数据集合,在该方法中没有特殊逻辑。

场景2:使用add()

Set<String> uniqueSet = new HashSet<String>();
getSomedata(param1, uniqueSet);
getSomedata(param2, uniqueSet );

此处getSomedata()如下

void getSomedata(String param, Set<String> uniqueSet){
    while (someCollection.hasNext()){
        uniqueSet.add( someCollection.get() );
    }
}

2 个答案:

答案 0 :(得分:1)

addAll基本上迭代它给出的集合,并在每个方法上调用add。这是OpenJDK8实现它的方式:

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

但作为一般的经验法则,你不应该试图发明轮子,除非你绝对确定你能发明一个更好的轮子。

答案 1 :(得分:1)

您的问题不完整。让我们用实际的替代方案来完成它。

首先,您有一个方法可以填充提供的Set

void getSomedata(String param, Set<String> uniqueSet)

必须像

一样使用
Set<String> uniqueSet = new HashSet<String>();
getSomedata(param1, uniqueSet);
getSomedata(param2, uniqueSet);

另一种方法是使用一个返回新Set的方法:

Set<String> getSomedata(String param)

你可以使用

Set<String> uniqueSet = getSomedata(param1);
uniqueSet.addAll( getSomedata(param2) );

在这种情况下,您忽略了方法getSomedata将如何创建并填充它将返回的Set。显然,除非它创建一个预测源数据的自定义Set实现,否则它必须创建一个Set并在返回之前用元素填充它。

换句话说,无论如何实现addAll,在您调用它时,此解决方案已经执行了与其他替代方案相同的工作,因为它已经添加了Set的所有元素。因此,即使特定addAll实现的Set具有优化功能,它的工作也会增加已经执行的将所有元素单独添加到Set的工作。

尽管如此,除非存在真正的性能问题,否则您不应该担心性能的规则。涉及的I / O可能会超过它。或者热点优化和内存管理效果的不可预测性可能会改变这一切。如果您认为getSomedate返回新的Set更清晰(这是合理的),请使用它。

作为附录,我简化了一下。 HashSet仅在理论上为O(1),但在存在哈希冲突时执行不同,并且在使用TreeSet s的情况下,O(log n)时间复杂度不同集合的大小有影响,因此根据使用的Set实现和其他周围环境,在不同大小的集合上运行的备选方案不具有完全可比性。但趋势仍然相同,特别是在大多数情况下,没有优化的addAll实现(EnumSet可能是唯一的例外)。