找出两个排序列表是否包含相同元素Java的有效方法。

时间:2016-07-08 17:55:25

标签: java performance new-operator

我有一个紧密的循环来搜索互质。列表primeFactors。它的第n个元素包含n的素数分解的排序列表。我正在使用c

检查dcheckIfPrimes是否是互质
boolean checkIfPrimes(int c, int d, List<List<Integer>> primeFactors) {
    List<Integer>  common = new ArrayList<>(primeFactors.get(d)); //slow
    common.retainAll(primeFactors.get(c));        
    return (common.isEmpty());
}

primeFactors.get(d).retainAll(primeFactors.get(c))看起来很有希望,但它会改变我的可重用primeFactors对象。

创建新对象相对较慢。有没有办法加快这一步?我可以以某种方式利用列表排序的事实吗?我应该使用数组吗?

5 个答案:

答案 0 :(得分:2)

您可以使用Collection快速查找 - 例如a Set如果您只需要素数而不重复,或Map如果您还需要每个因素的计数。

基本上,您想知道两个集合的交集是否为空。 Oracle Set tutorial显示了一种计算相交的方法(类似于您已经提到的,在副本上使用retainAll,但在设置上操作应该更有效)。

答案 1 :(得分:2)

由于您的列表相对较小,并且此操作经常执行,因此您应该避免创建任何新的列表或集合,因为它可能会导致GC的巨大压力。

扫描线性算法

public static boolean emptyIntersection(List<Integer> sortedA, List<Integer> sortedB) {
    if (sortedA.isEmpty() || sortedB.isEmpty())
        return true;
    int sizeA = sortedA.size(), sizeB = sortedB.size();
    int indexA = 0, indexB = 0;
    int elementA = sortedA.get(indexA), elementB = sortedB.get(indexB);
    while (true) {
        if (elementA == elementB) {
            return false;
        } else if (elementA < elementB) {
            indexA++;
            if (indexA == sizeA)
                return true;
            elementA = sortedA.get(indexA);
        } else {
            // elementB < elementA
            indexB++;
            if (indexB == sizeB)
                return true;
            elementB = sortedB.get(indexB);
        }
    }
}

还要考虑使用原始int s的列表而不是盒装整数,例如: G。来自fastutil图书馆。

答案 2 :(得分:1)

通常你可以使用布尔数组。其中数组的索引是数字,并且当布尔值为true时,布尔值返回false

答案 3 :(得分:1)

您可以采取以下措施:

List<Integer> commonElements = 
       primeFactors.get(d).stream()
                          .filter(primeFactors.get(c)::contains)
                          .collect(Collectors.toList());

一旦你衡量了这个表现,你可以用'parallelStream()'代替上面的'stream()',看看你得到了什么好处。

答案 4 :(得分:1)

设置操作应该比数组操作更快。 只是为了解决问题,请考虑尝试并将性能与流性能进行比较:

final Set<Integer> commonSet;
final Set<Integer> cSet = new HashSet<Integer>();
final Set<Integer> dSet = new HashSet<Integer>();

cSet.addAll(primeFactors.get(c));
dSet.addAll(primeFactors.get(d));

commonSet = dSet.retainAll(cSet);

return (commonSet.isEmpty());

另外, 考虑使用List<Set<Integer>> primeFactors 而不是List<List<Integer>> primeFactors,因为我怀疑你不这样做 确实有一系列素因子,但实际上有一组素因子。