Java 8-合并包含公共元素的所有子集

Java 8-合并包含公共元素的所有子集,java,merge,java-8,set,Java,Merge,Java 8,Set,从一组“组”开始: 最终结果将是: Set 1 = {a, b, c, d, e, f, g, h, i, j} Set 2 = {k, l, m, n, o} Set 3 = {p, q, r} 任何关于如何实现这一点的建议都将不胜感激 编辑:如果集合不均匀,它将执行相同的操作。因此,如果它是一个方法,它将如下所示: public void doStuff(){ Set<Set<String>> groups = {{a,b,c}, {c,d,e,f}, {m,

从一组“组”开始:

最终结果将是:

Set 1 = {a, b, c, d, e, f, g, h, i, j}
Set 2 = {k, l, m, n, o}
Set 3 = {p, q, r}
任何关于如何实现这一点的建议都将不胜感激

编辑:如果集合不均匀,它将执行相同的操作。因此,如果它是一个方法,它将如下所示:

public void doStuff(){

  Set<Set<String>> groups = {{a,b,c}, {c,d,e,f}, {m, n, o}}

  Set<Set<String>> newGroups = mergeSubsets(groups);

  System.out.println(newGroups);
}

public Set<Set<String>> mergeSubsets(Set<Set<String>> groups){

     //some operations

}
import java.util.*;
公共类合并集{
公共静态void main(字符串…参数){
列表组=新的ArrayList();
字符串[]A={“A”,“b”,“c”};
字符串[]B={“c”,“d”,“e”,“f”};
字符串[]C={“f”、“g”、“h”、“i”、“j”};
字符串[]D={“k”,“l”,“m”};
字符串[]E={“m”,“n”,“o”};
字符串[]F={“p”,“q”,“r”};
add(新的HashSet(Arrays.asList(A));
add(新的HashSet(Arrays.asList(B));
add(新的HashSet(Arrays.asList(C));
add(新的HashSet(Arrays.asList(D));
add(新的HashSet(Arrays.asList(E));
add(新的HashSet(Arrays.asList(F));
Set newGroups=合并子集(组);
System.out.println(新组);
}
私有静态集合合并子集(列表组){
List newGroups=newarraylist();
Set init=groups.get(0);
组。移除(0);
newGroups.add(init);
而(!groups.isEmpty()){
从groupandupdatenewgroup(newGroups.get(newGroups.size()-1),groups)中删除mergedelement;
如果(!groups.isEmpty()){
init=groups.get(0);
组。移除(0);
newGroups.add(init);
}
}
返回新的HashSet(newGroups);
}
私有静态void removeMergedElementFromGroupAndUpdateNewGroup(设置master2,列表masterList){
迭代器迭代器=masterList.Iterator();
while(iterator.hasNext()){
Set strings=iterator.next();
布尔合并=strings.stream().anyMatch(string->master2.contains(string));
如果(合并){
master2.addAll(字符串);
iterator.remove();
}
}
}
}
希望这有助于取代
集合组
我使用了
列表组
以便于使用列表如果您有仅使用Set的限制,您可以通过将Set(比如yourSet)传递到List实现的构造函数中,从Set生成List,例如

groups = new ArrayList<>(yourSet);
groups=newarraylist(yourSet);

您可以按照您在问题陈述中描述的方式实现算法——找到相交集并合并它们,直到没有任何东西可合并为止。标准库有一种方法可以帮助确定两个集合是否有任何共同元素:

// this implementation sacrifices efficiency for clarity
public Set<Set<String>> mergeSubsets(Set<Set<String>> groups) {
    Set<Set<String>> result = new HashSet<>();
    for (Set<String> set : groups) {
        // try to find a set in result that intersects this set
        // if one is found, merge the two.  otherwise, add this set to result
        result.stream()
                .filter(x -> !Collections.disjoint(x, set))
                .findAny()
                .ifPresentOrElse(   // this method was added in java 9
                        x -> x.addAll(set),
                        () -> result.add(new HashSet<>(set))
                );
    }

    // if nothing got merged we are done; otherwise, recurse and try again
    return result.size() == groups.size() ? result : mergeSubsets(result);
}
//为了清晰起见,此实现牺牲了效率
公共集合合并子集(集合组){
Set result=new HashSet();
用于(集合:组){
//尝试在结果中找到与此集合相交的集合
//如果找到一个,则合并两个。否则,将此集合添加到结果
result.stream()
.filter(x->!集合.不相交(x,集合))
.findAny()
.ifPresentOrElse(//此方法是在java 9中添加的
x->x.addAll(设置),
()->result.add(新哈希集(set))
);
}
//如果没有合并任何内容,我们就完成了;否则,递归并重试
返回result.size()==groups.size()?结果:合并子集(结果);
}

以下是基于@NiksVij解决方案的命令式方法。显然,@NiksVij的解决方案是不正确的,这个答案旨在解决这个问题并进一步扩展:

public class MergeSet {

    public static void main(String... args) {
        List<Set<String>> list = new ArrayList<>();
        String[] A = {"a", "c", "e", "g"};
        String[] B = {"b", "d", "f", "h"};
        String[] C = {"c", "e", "f"};
        String[] D = {"b"};

        list.add(new HashSet<>(Arrays.asList(A)));
        list.add(new HashSet<>(Arrays.asList(C)));
        list.add(new HashSet<>(Arrays.asList(B)));
        list.add(new HashSet<>(Arrays.asList(D)));

        List<Set<String>> newGroups = merge(list);
        System.out.println(newGroups);

    }

    @SuppressWarnings("empty-statement")
    private static <T> List<Set<T>> merge(List<Set<T>> list) {
        if (list == null || list.isEmpty()) {
            return list;
        }
        List<Set<T>> merged = new ArrayList<>();
        do {
            merged.add(list.get(0));
            list.remove(0);

            while (mergeStep(merged.get(merged.size() - 1), list));
        } while (!list.isEmpty());
        return merged;
    }

    private static <T> boolean mergeStep(Set<T> setToCheck, List<Set<T>> remainingList) {
        boolean atLeastOnceMerged = false;
        Iterator<Set<T>> iterator = remainingList.iterator();
        while (iterator.hasNext()) {
            Set<T> elements = iterator.next();
            boolean doMerge = !Collections.disjoint(elements, setToCheck);
            if (doMerge) {
                atLeastOnceMerged |= doMerge;
                setToCheck.addAll(elements);
                iterator.remove();
            }
        }
        return atLeastOnceMerged;
    }
公共类合并集{
公共静态void main(字符串…参数){
列表=新的ArrayList();
字符串[]A={“A”、“c”、“e”、“g”};
字符串[]B={“B”,“d”,“f”,“h”};
字符串[]C={“C”,“e”,“f”};
字符串[]D={“b”};
add(新的HashSet(Arrays.asList(A));
add(新的HashSet(Arrays.asList(C));
add(新的HashSet(Arrays.asList(B));
add(新的HashSet(Arrays.asList(D));
列表新建组=合并(列表);
System.out.println(新组);
}
@SuppressWarnings(“空语句”)
私有静态列表合并(列表){
if(list==null | | list.isEmpty()){
退货清单;
}
列表合并=新建ArrayList();
做{
merged.add(list.get(0));
列表。删除(0);
while(mergeStep(merged.get(merged.size()-1),list));
}而(!list.isEmpty());
返回合并;
}
私有静态布尔合并步骤(设置setToCheck,列表remainingList){
布尔值AtleastOnce=false;
迭代器迭代器=remainingList.Iterator();
while(iterator.hasNext()){
Set elements=iterator.next();
布尔值doMerge=!Collections.disjoint(elements,setToCheck);
如果(多梅尔奇){
至少|=多梅尔奇;
setToCheck.addAll(元素);
iterator.remove();
}
}
至少返回一次;
}

你试图达到相同的目的是什么?集合1、2、3的分组逻辑是什么?任何由非空交集组成的任意两个子集都应该合并。我相信它适合某种递归解决方案,但我很难弄清楚这一点。在纸上解决它-显然背后有一个算法然后写Java代码你的结果集怎么会有两个
c
s?好吧,我做得更好,{{a,b,c},{c,d,e,f},{e,n,o},这个结果会是什么?这对
String[]a={a”,“c”,“e”,“e”,“g};String[]b={b”,“d”,“f”,“h};String[]c={c”,“c”,“e”,“f};String[]D={“b”};
逻辑正常。它缺少一个空检查。我们添加了该检查。感谢您指出缺少的内容
import java.util.*;

public class MergeSet {
    public static void main(String... args) {
        List<Set<String>> groups = new ArrayList<>();
        String[] A = {"a", "b", "c"};
        String[] B = {"c", "d", "e", "f"};
        String[] C = {"f", "g", "h", "i", "j"};
        String[] D = {"k", "l", "m"};
        String[] E = {"m", "n", "o"};
        String[] F = {"p", "q", "r"};

        groups.add(new HashSet<>(Arrays.asList(A)));
        groups.add(new HashSet<>(Arrays.asList(B)));
        groups.add(new HashSet<>(Arrays.asList(C)));
        groups.add(new HashSet<>(Arrays.asList(D)));
        groups.add(new HashSet<>(Arrays.asList(E)));
        groups.add(new HashSet<>(Arrays.asList(F)));

        Set<Set<String>> newGroups = mergeSubsets(groups);
        System.out.println(newGroups);

    }

    private static Set<Set<String>> mergeSubsets(List<Set<String>> groups) {
        List<Set<String>> newGroups = new ArrayList<>();
        Set<String> init = groups.get(0);
        groups.remove(0);
        newGroups.add(init);
        while (!groups.isEmpty()) {
            removeMergedElementFromGroupAndUpdateNewGroup(newGroups.get(newGroups.size() - 1), groups);
            if(!groups.isEmpty()) {
                init = groups.get(0);
                groups.remove(0);
                newGroups.add(init);
            }
        }
        return new HashSet<>(newGroups);
    }

    private static void removeMergedElementFromGroupAndUpdateNewGroup(Set<String> master2, List<Set<String>> masterList) {
        Iterator<Set<String>> iterator = masterList.iterator();
        while (iterator.hasNext()) {
            Set<String> strings = iterator.next();
            boolean merge = strings.stream().anyMatch(string -> master2.contains(string));
            if (merge) {
                master2.addAll(strings);
                iterator.remove();
            }
        }
    }
}
groups = new ArrayList<>(yourSet);
// this implementation sacrifices efficiency for clarity
public Set<Set<String>> mergeSubsets(Set<Set<String>> groups) {
    Set<Set<String>> result = new HashSet<>();
    for (Set<String> set : groups) {
        // try to find a set in result that intersects this set
        // if one is found, merge the two.  otherwise, add this set to result
        result.stream()
                .filter(x -> !Collections.disjoint(x, set))
                .findAny()
                .ifPresentOrElse(   // this method was added in java 9
                        x -> x.addAll(set),
                        () -> result.add(new HashSet<>(set))
                );
    }

    // if nothing got merged we are done; otherwise, recurse and try again
    return result.size() == groups.size() ? result : mergeSubsets(result);
}
public class MergeSet {

    public static void main(String... args) {
        List<Set<String>> list = new ArrayList<>();
        String[] A = {"a", "c", "e", "g"};
        String[] B = {"b", "d", "f", "h"};
        String[] C = {"c", "e", "f"};
        String[] D = {"b"};

        list.add(new HashSet<>(Arrays.asList(A)));
        list.add(new HashSet<>(Arrays.asList(C)));
        list.add(new HashSet<>(Arrays.asList(B)));
        list.add(new HashSet<>(Arrays.asList(D)));

        List<Set<String>> newGroups = merge(list);
        System.out.println(newGroups);

    }

    @SuppressWarnings("empty-statement")
    private static <T> List<Set<T>> merge(List<Set<T>> list) {
        if (list == null || list.isEmpty()) {
            return list;
        }
        List<Set<T>> merged = new ArrayList<>();
        do {
            merged.add(list.get(0));
            list.remove(0);

            while (mergeStep(merged.get(merged.size() - 1), list));
        } while (!list.isEmpty());
        return merged;
    }

    private static <T> boolean mergeStep(Set<T> setToCheck, List<Set<T>> remainingList) {
        boolean atLeastOnceMerged = false;
        Iterator<Set<T>> iterator = remainingList.iterator();
        while (iterator.hasNext()) {
            Set<T> elements = iterator.next();
            boolean doMerge = !Collections.disjoint(elements, setToCheck);
            if (doMerge) {
                atLeastOnceMerged |= doMerge;
                setToCheck.addAll(elements);
                iterator.remove();
            }
        }
        return atLeastOnceMerged;
    }