集合中的相等性<Set> Java
Equality in Set<Set> Java
我有一个方法 returns Set<Set<String>>
。在我的测试中,我正在尝试使用 contains()
方法检查预期的 Set
是否存在。
例如。 input = "cat", "dog", "god"
output = [[cat], [dog, god]]
现在,如果我 output.contains(new HashSet<>(Arrays.asList("cat")))
它 return 就会 true
。
但是如果我这样做 output.contains(new HashSet<>(Arrays.asList("dog", "god")))
它 returns false
.
根据我的理解,这两种情况都应该return 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);
}
}
当您使用 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))
问题出在您的 findAndAdd
方法中,您正在改变外部 Set
(groups
) 的一个元素 (group
),因此改变了它的 hashCode()
。结果,groups.contains(set2)
找不到 groups
中存在的 Set
,因为它在错误的存储桶(匹配新的 hashCode()
)而不是存储桶中查找它它被添加到其中(匹配原始 hashCode()
)。
您可以通过在更改 groups
之前删除 group
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) {
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]]
试试这个。
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]}
我有一个方法 returns Set<Set<String>>
。在我的测试中,我正在尝试使用 contains()
方法检查预期的 Set
是否存在。
例如。 input = "cat", "dog", "god"
output = [[cat], [dog, god]]
现在,如果我 output.contains(new HashSet<>(Arrays.asList("cat")))
它 return 就会 true
。
但是如果我这样做 output.contains(new HashSet<>(Arrays.asList("dog", "god")))
它 returns false
.
根据我的理解,这两种情况都应该return 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);
}
}
当您使用 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))
问题出在您的 findAndAdd
方法中,您正在改变外部 Set
(groups
) 的一个元素 (group
),因此改变了它的 hashCode()
。结果,groups.contains(set2)
找不到 groups
中存在的 Set
,因为它在错误的存储桶(匹配新的 hashCode()
)而不是存储桶中查找它它被添加到其中(匹配原始 hashCode()
)。
您可以通过在更改 groups
之前删除 group
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) {
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]]
试试这个。
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]}