繁体   English   中英

计算Java集合差异或交集的性能

[英]Performance of calculating Java Collection difference or intersection

Java允许通过Collection接口removeAll()retainAll()方法来计算(设置理论上的)差和两个Collection对象的交集

这两个方法在Java 6的AbstractCollection类中的实现是

public boolean removeAll(Collection<?> c) { // Difference
boolean modified = false;
Iterator<?> e = iterator();
while (e.hasNext()) {
    if (c.contains(e.next())) {
    e.remove();
    modified = true;
    }
}
return modified;
}

public boolean retainAll(Collection<?> c) { // Intersection
boolean modified = false;
Iterator<E> e = iterator();
while (e.hasNext()) {
    if (!c.contains(e.next())) {
    e.remove();
    modified = true;
    }
}
return modified;
}

有什么方法可以更快地实现或执行上述(显然是昂贵的)操作?

例如,在计算差异或交集之前对Collection进行排序会带来整体性能提升吗?

对于这些操作,是否有Collections框架的任何类更可取(在性能方面)?

是的,有一种更快的方法。 您提供的代码针对e的每个元素在c中循环。 使用100个元素的两个数组,它将比较大约100,000个元素。

如果先对两个数组进行排序,则只需比较前两个元素。 这将进行数百次比较。 这将类似于合并排序。 不要做排序的集合的交集leftright

function intersect(left, right)
    var list result
    while length(left) > 0 and length(right) > 0
        if first(left) == first(right)
            append first(left) to result
            left = rest(left)
            right = rest(right)
        else if first(left) < first(right)
            left = rest(left)
        else
            right = rest(right)
    end while
    return result

这些实现位于AbstractCollection ,因此它们非常通用,因为在此抽象级别上,对集合的了解很少,可用操作的数量非常有限。 仅考虑Collection接口允许的内容,并且不了解任何有关收集类型及其实现细节的信息,很难做到更聪明。 排序是否有效取决于所讨论的集合的大小和类型,在此级别上代码无法得知。

阅读AbstractCollection的javadoc:

要实现不可修改的集合,程序员只需扩展此类并为iterator [...]提供实现。

因此,我相信您应该检查如何为特定的类实现Iterator,以真正了解这些方法的性能。

有什么方法可以更快地实现或执行上述(显然是昂贵的)操作?

这些操作的实际成本多少取决于作为参数传递的集合如何实现contains()。 如果它是HashSet ,则contains是一个常数(预期)时间操作,导致removeAllretainAll在线性(预期)时间内完成。

排序会更昂贵。

而且,在Set上完成set操作是最高效的,这是合理的,不是吗?

如果集合中的元素是枚举或密集整数,则可以使用EnumSetBitSet获得更快的速度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM