找到多个集合之间的交集

时间:2015-12-17 13:57:18

标签: java algorithm set intersection

我有不同的名字集。每组包含不同数量的字符串。我想知道哪个集合与哪个集合相交。我写了以下算法(未经测试)

//initial structure key= set name, value = actual set
Map<String, Set<String>> namedSets = new LinkedHashMap<String, Set<String>>();

//get a list of all sets 
List<Set<String>> sets = new ArrayList<Set<String>>(namedSets.values());
List<String> names = new ArrayList<String>(namedSets.keySet());

while (!sets.isEmpty()){
    Set<String> examinedSet = sets.remove(0); //remove it because it will be checked sortly. 
    String name = names.remove(0); //remove its name too.
    //check it with remaining sets
    for (Set<String> set : sets){
        //there are common elements inside the two sets, 
        if (!Collections.disjoint(examinedSet, set)
            addIntersection(name, names.get(names.indexOf(set)));
    }

public void addIntersection(name, intersectedName){
    if (conflictedSets.containsKey(name){
        conflictedSets.get(name).add(intersectedName);

    }else{
        List<String> intersectedNames = new ArrayList<String>();
        intersectedNames.add(intersectedName);
        conflictedSets.put(name, intersectedNames);
    }
}

我不喜欢我必须做这个嵌套循环的事实,尽管对于它的迭代它完成了一个循环,因为已检查的名称从列表中删除。有更有效的方法吗?我的问题是,我不想检查它们是否相交,但是哪一个是相交的。有更高效的算法吗?     }

1 个答案:

答案 0 :(得分:0)

这样的事情怎么样?对不起,Java8并不算太多。但是,我们的想法是将所有内容放入哈希表中,然后将包含至少1个共同元素的元素视为相交。我测试了它,它的工作原理。由于内存的原因,这不能很好地扩展,因此如果您的集合包含数百万条目,那么它可能不是最佳选择。但是它在O(N)时间内运行,N是所有集合中的条目数。我也假设N&lt;&lt;套数。

import java.util.*;

class Main {
  public static void main(String[] args) {

    // Just adding data here

    Set<String> set1 = new HashSet<>();
    set1.add("a"); set1.add("b"); set1.add("c"); 

    Set<String> set2 = new HashSet<>();
    set2.add("a"); set2.add("z"); set2.add("j"); 

    Set<String> set3 = new HashSet<>();
    set3.add("n"); set3.add("d"); set3.add("f"); 

    //initial structure key= set name, value = actual set
    Map<String, Set<String>> namedSets = new LinkedHashMap<String, Set<String>>();

    namedSets.put("set1", set1);
    namedSets.put("set2", set2);
    namedSets.put("set3", set3);

    // Real code
    Map<String, ArrayList<Set<String>>> hashInter = new HashMap<>();
    Set<Map.Entry<Set<String>, Set<String>>> result = new HashSet<>();

    for (Map.Entry<String, Set<String>> entry : namedSets.entrySet()) {
        for (String s : entry.getValue()) {
            if (!hashInter.containsKey(s)) {
                hashInter.put(s, new ArrayList<Set<String>>());
            }

            hashInter.get(s).add(entry.getValue());

        }
    }


    for (Map.Entry<String, ArrayList<Set<String>>> entry : hashInter.entrySet()) {
        ArrayList<Set<String>> vals = entry.getValue();

        for (int i = 0; i < vals.size(); i++) {
            for (int j = 0; j < vals.size(); j++) {
                if (i >= j) {
                    continue;
                }
                Map.Entry<Set<String>, Set<String>> entryInter = new AbstractMap.SimpleEntry<Set<String>, Set<String>>(vals.get(i), vals.get(j));
                result.add(entryInter);
            }
        }
    }

    result.stream().forEach(e -> System.out.println(e.getValue() + " " + e.getKey()));
  }
}

产量

[a, z, j] [a, b, c]