Равенство в наборе <Set>Java - PullRequest
0 голосов
/ 12 июня 2018

У меня есть метод, который возвращает 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 в обоих случаях.

Чего мне не хватаетВот?

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);
     }
}

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Проблема заключается в вашем методе findAndAdd, когда вы изменяете элемент (group) внешнего Set (groups), изменяя его hashCode().В результате groups.contains(set2) не может найти Set, который присутствует в groups, поскольку он ищет его в неправильном сегменте (соответствует новому hashCode()) вместо того, в который он был добавлен (соответствуетoriginal hashCode()).

Вы можете исправить свой код, удалив group Set из 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 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 в обоих случаях.

Вывод:

[[cat], [god, dog]]
true
true
[[cat], [god, dog]]
0 голосов
/ 12 июня 2018

Попробуйте это.

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());
}

И

Set<String> words = new HashSet<>(Arrays.asList("cat", "dog", "god"));
System.out.println(group(words));

Результат:

[[cat], [god, dog]]

Промежуточная переменная map имеет

{act=[cat], dgo=[god, dog]}
0 голосов
/ 12 июня 2018

Когда вы используете Set set2 = new HashSet<>(Arrays.asList("god", "dog")); Вы не проверяете комбинацию "god" and "dog", но вы проверяете для каждого элемента god, тогда dog существуют в вашем Set<Set<String>> или нет, и в вашем наборе у вас есть только одинэлемент cat отделен.это как:

groups contains `god` -> no
groups contains `dog` -> no

return false

Чтобы решить вашу проблему, вы можете использовать равные, например, так:

groups.stream().anyMatch(a -> a.equals(set2))// or groups.stream().anyMatch(set2::equals)

или

groups.stream().anyMatch(a -> a.containsAll(set2))
...