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() );
}
}
答案 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
可能是唯一的例外)。