簡體   English   中英

有效地確定兩個集合是否在Java中具有任何共同的項目

[英]Efficiently determining whether or not two collections have any items in common in Java

我知道,在Java中,我可以手動確定兩個集合是否有重疊,方法是將其中一個集合轉換為集合,然后迭代另一個集合進行包含檢查:

<T> boolean anyInCommon(Iterable<T> collection1, Set<T> collection2) {
    for (T item : collection1)
        if (collection2.contains(item))
            return true;
    return false;
}

或者:

<T> boolean anyInCommon(Iterable<T> collection1, Set<T> collection2) {
    return collection1.stream().anyMatch(collection2::contains);
}

但是有沒有現成的實用方法可以做到這一點並智能地選擇要迭代的集合,哪些集合變成集合,利用已經成為集合的集合等等? 我知道Guava有Sets.intersection ,但是它計算整個交集,而不僅僅是它是否為空。

請注意,一旦找到任何常見項目,我寧願將比較與短路相關聯。 檢查兩個巨大的集合是否有重疊應該花費與非重疊項目(或更好)的數量成比例的時間,而不是項目的總數。

集合已經設置時的部分答案。

Sets.intersection實際上比我想的更接近我的想法,因為它的結果不是預先計算的。 相反, 它是在飛行中計算的交叉點視圖

看看intersection返回的匿名類

final Predicate<Object> inSet2 = Predicates.in(set2);
return new SetView<E>() {
  @Override public Iterator<E> iterator() {
    return Iterators.filter(set1.iterator(), inSet2);
  }
  @Override public int size() {
    return Iterators.size(iterator());
  }
  @Override public boolean isEmpty() {
    return !iterator().hasNext();
  }
  @Override public boolean contains(Object object) {
    return set1.contains(object) && set2.contains(object);
  }
  @Override public boolean containsAll(Collection<?> collection) {
    return set1.containsAll(collection)
        && set2.containsAll(collection);
  }
};

isEmpty方法不會覆蓋每個項目。 相反,它會在檢查項目是否在第二組中時迭代第一組。 一找到它,它就會返回true。 如果你運氣不好,你將首先迭代set1中不在set2中的所有項目,但這可能是不可避免的,並且比總是迭代所有項目更好。

換句話說, 如果您已經擁有集合 ,那么適當短路的有效解決方案就是:

boolean overlaps = !Sets.intersections(set1, set2).isEmpty();

這不會迭代較小的集合而不是較大的集合,或處理非集合集合,但它通常是有用的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM