首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Set<Set> Java中的等式

Set<Set> Java中的等式
EN

Stack Overflow用户
提问于 2018-06-12 11:35:31
回答 3查看 178关注 0票数 8

我有一个返回Set<Set<String>>的方法。在我的测试中,我试图使用Set方法检查预期的contains()是否存在。

例如:input = "cat", "dog", "god"

output = [[cat], [dog, god]]

现在,如果我执行output.contains(new HashSet<>(Arrays.asList("cat"))),它将返回true

但是如果我做了output.contains(new HashSet<>(Arrays.asList("dog", "god"))),它会返回false

根据我的理解,在这两种情况下它都应该返回true

我在这里错过了什么?

代码语言:javascript
复制
public class AnagramGroups {
     public Set<Set<String>> group(Set<String> words) {
         Set<Set<String>> groups = new HashSet<>();
         for(String word: words) {
             findAndAdd(word, groups);
         }
         return groups;
     }

     private void findAndAdd(String word, Set<Set<String>> groups) {
         for(Set<String> group: groups) {
             boolean found = false;
             for(String str: group) {
                 if(isAnagram(str, word)) {
                     found = true;
                 }
                 break;
             }
             if(found) {
                 group.add(word);
                 return;
             }
         }
         Set<String> set = new HashSet<>();
         set.add(word);
         groups.add(set);
     }

     private boolean isAnagram(String str, String word) {
         Set<Character> characters = new HashSet<>();
         for(char c: str.toCharArray()) {
             characters.add(c);
         }
         for(char c: word.toCharArray()) {
             if(!characters.contains(c)) {
                 return false;
             }
             characters.remove(c);
         }
         return characters.isEmpty();
     }

     public static void main(String[] args) {
         Set<Set<String>> groups = new AnagramGroups()
             .group(new HashSet<>(Arrays.asList("cat", "god", "dog")));
         System.out.println(groups);

         Set set1 = new HashSet<>(Arrays.asList("cat"));
         Set set2 = new HashSet<>(Arrays.asList("god", "dog"));
         System.out.println(groups.contains(set1));
         System.out.println(groups.contains(set2));

         groups.add(new HashSet<>(Arrays.asList("god", "dog")));
         System.out.println(groups);
     }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-12 11:46:45

问题在您的findAndAdd方法中,您正在变异外部Set (groups)的一个元素(group),因此更改它的hashCode()。因此,groups.contains(set2)无法找到groups中存在的Set,因为它在错误的桶(匹配新的hashCode())中查找,而不是在添加到的桶(匹配原始hashCode())中查找。

您可以在修改代码之前从group Set中删除groups,然后重新添加代码来修复代码。

将代码更改为:

代码语言:javascript
复制
 private void findAndAdd(String word, Set<Set<String>> groups) {
     for(Set<String> group: groups) {
         boolean found = false;
         for(String str: group) {
             if(isAnagram(str, word)) {
                 found = true;
             }
             break;
         }
         if(found) {
             group.add(word);
             return;
         }
     }
     Set<String> set = new HashSet<>();
     set.add(word);
     groups.add(set);
 }

至:

代码语言:javascript
复制
 private void findAndAdd(String word, Set<Set<String>> groups) {
     for(Set<String> group: groups) {
         boolean found = false;
         for(String str: group) {
             if(isAnagram(str, word)) {
                 found = true;
             }
             break;
         }
         if(found) {
             groups.remove(group);
             group.add (word);
             groups.add(group);
             return;
         }
     }
     Set<String> set = new HashSet<>();
     set.add(word);
     groups.add(set);
 }

当我尝试您的代码并进行更改时,在这两种情况下我都得到了true

输出:

代码语言:javascript
复制
[[cat], [god, dog]]
true
true
[[cat], [god, dog]]
票数 4
EN

Stack Overflow用户

发布于 2018-06-12 11:45:54

当您使用Set set2 = new HashSet<>(Arrays.asList("god", "dog"));时,您不是在检查组合"god" and "dog",而是检查每个元素god,然后dog是否存在于您的Set<Set<String>>中,并且在您的集合中只有一个元素cat是分开的。就像:

代码语言:javascript
复制
groups contains `god` -> no
groups contains `dog` -> no

return false

要解决您的问题,您可以像这样使用等号:

代码语言:javascript
复制
groups.stream().anyMatch(a -> a.equals(set2))// or groups.stream().anyMatch(set2::equals)

代码语言:javascript
复制
groups.stream().anyMatch(a -> a.containsAll(set2))
票数 0
EN

Stack Overflow用户

发布于 2018-06-12 13:11:02

尝尝这个。

代码语言:javascript
复制
static String sort(String s) {
    int[] sortedCP = s.codePoints().sorted().toArray();
    return new String(sortedCP, 0, sortedCP.length);
}

public static Set<Set<String>> group(Set<String> words) {
    Map<String, Set<String>> map = new HashMap<>();
    for (String word : words)
        map.computeIfAbsent(sort(word), k -> new HashSet<>()).add(word);
    return new HashSet<>(map.values());
}

代码语言:javascript
复制
Set<String> words = new HashSet<>(Arrays.asList("cat", "dog", "god"));
System.out.println(group(words));

结果:

代码语言:javascript
复制
[[cat], [god, dog]]

中间变量map

代码语言:javascript
复制
{act=[cat], dgo=[god, dog]}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50816180

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档