Java集合API哈希集删除方法
我在使用Java Collections API时遇到了这个问题。基本上,这是Kruskal查找MST算法实现的支持方法。我创建这个类是为了实现union/find算法 我的问题是,当我能够找到一种解决方法时,有人知道为什么“联合”方法中的remove方法不能一直工作吗。也就是说,在运行时,它将删除一些元素,而不是其他元素。例如,我为一项涉及城市的任务实施了这项任务,它似乎不像移除一些城市。特别是,它反复发现了几个不同的场景,但总是相同的场景。我想知道这是否是一个对象引用问题,即我是否测试了错误的东西,但我无法回避它 我知道我的其余工作是正确的,因为我能够用一个消除元素的循环来替换它,并且算法执行得非常完美。不过,性能可能稍差一些 我想知道是否有人能看出一个错误。我还应该注意,我从不同的类调用了它,但是,调用是使用find方法检索的元素进行的。请注意,find方法必须很好地工作,因为简单地修改remove方法就可以完成整个工作,即查找并返回适当的对象 谢谢 奥斯卡Java集合API哈希集删除方法,java,hashset,Java,Hashset,我在使用Java Collections API时遇到了这个问题。基本上,这是Kruskal查找MST算法实现的支持方法。我创建这个类是为了实现union/find算法 我的问题是,当我能够找到一种解决方法时,有人知道为什么“联合”方法中的remove方法不能一直工作吗。也就是说,在运行时,它将删除一些元素,而不是其他元素。例如,我为一项涉及城市的任务实施了这项任务,它似乎不像移除一些城市。特别是,它反复发现了几个不同的场景,但总是相同的场景。我想知道这是否是一个对象引用问题,即我是否测试了错误
/*
*用于创建此类的新对象的构造函数。
*/
不相交集()
{
底层=新HashSet();
}
/*
*将集合添加到此DisjointSets对象的方法
*/
无效添加(哈希集h)
{
添加(h);
}
/*
*用于在此不相交集对象中查找元素的方法。
*/
哈希集查找(字符串s)
{
//检查DisjointSets对象中的每个集合
for(哈希集h:基础)
{
如果(h.包含)
{
返回h;
}
}
返回null;
}
/*
*不相交集子集的一种组合方法
*/
无效并集(哈希集h1、哈希集h2)
{
System.out.print(“检查DS\n”);
系统输出打印(“***************************\n”);
System.out.print(“H1为:{”);
for(哈希集n:基础)
{
System.out.print(“设置为:{”);
for(字符串h:n)
{
系统输出打印(h+“,”);
}
System.out.print(“}\n”);
}
//将h1的对象添加到h2
//不能始终如一地工作
h1.addAll(h2);
移除(h2);
}
}
我把它换成了
HashSet<HashSet<String>> temp = new HashSet<HashSet<String>>();
for(HashSet<String> f: underlying)
{
if(f != h2)
{
temp.add(f);
}
}
underlying = temp;
HashSet temp=new HashSet();
for(哈希集f:基础)
{
如果(f!=h2)
{
温度添加(f);
}
}
基础=温度;
问题在于,当您修改其中一个嵌套哈希集的内容时,您会破坏外部哈希集的内部结构(因为嵌套哈希集的hashCode()已更改)。为了正确维护此集合,每当您想要修改其中一个嵌套哈希集时,必须首先将其从外部哈希集中删除,然后重新添加(如果需要)
(您没有提供足够的代码来确定这是否是真正的问题,但这是我最好的猜测)
Set outerSet=new HashSet();
Set innerSet=new HashSet();
innerSet.add(“foo”);
添加(内部集合);
//***破损***
innerSet.add(“bar”);// 问题是,当您修改其中一个嵌套哈希集的内容时,会破坏外部哈希集的内部结构(因为嵌套哈希集的hashCode()已更改)。为了正确维护此集合,每当您想要修改其中一个嵌套哈希集时,必须首先将其从外部哈希集中删除,然后重新添加(如果需要)
(您没有提供足够的代码来确定这是否是真正的问题,但这是我最好的猜测)
Set outerSet=new HashSet();
Set innerSet=new HashSet();
innerSet.add(“foo”);
添加(内部集合);
//***破损***
innerSet.add(“bar”);// 根据@jtahlborn的回答,合同上说
返回此文件的哈希代码值
设置定义了集合的哈希代码
为的哈希代码之和
集合中的元素。这确保
s1.等于(s2)意味着
s1.hashCode()==s2.hashCode()用于任何
两套s1和s2,如制造商要求
Object.hashCode的总合同
此实现列举了超过
集合,调用hashCode方法
在集合中的每个元素上,以及
把结果加起来
用于演示@jtahlborn答案的代码(正确)
import java.util.HashSet;
导入java.util.Set;
公共类TestHashSetHashCode{
公共静态void main(字符串[]args)
{
Set strings=newhashset();
字符串。添加(“一”);
字符串。添加(“两个”);
字符串。添加(“三”);
字符串。添加(“四”);
字符串。添加(“五”);
Set test=新的HashSet();
System.out.println(“Code”+test.hashCode());
用于(字符串s:字符串){
测试。添加(s);
System.out.println(“Code”+test.hashCode());
}
}
}
输出
Code 0
Code 115276
Code 3258622
Code 3368804
Code 113708290
Code 116857384
代码0
代码115276
代码3258622
代码3368804
代码113708290
代码116857384
还有一个理由需要添加到列表中,以便尽可能利用不可变的集合。根据@jtahlborn的回答,该合同称
返回此文件的哈希代码值
设置定义了集合的哈希代码
为的哈希代码之和
集合中的元素。这确保
s1.等于(s2)意味着
s1.hashCode()==s2.hashCode()用于任何
两套s1和s2,如制造商要求
Object.hashCode的总合同
此实现列举了超过
集合,调用hashCode方法
在集合中的每个元素上,以及
把结果加起来
用于演示@jtahlborn答案的代码(正确)
import java.util.HashSet;
接口信息处理器
Set<Set<String>> outerSet = new HashSet<String>();
Set<String> innerSet = new HashSet<String>();
innerSet.add("foo");
outerSet.add(innerSet);
// *** BROKEN ***
innerSet.add("bar"); // <- adding element to innerSet changes result of innerSet.hashCode()
outerSet.remove(innerSet); // <- this may or may not work because outerSet is _broken_
// *** BROKEN ***
// *** CORRECT ***
outerSet.remove(innerSet);
innerSet.add("bar");
// now you can put innerSet back in outerSet if necessary
import java.util.HashSet;
import java.util.Set;
public class TestHashSetHashCode {
public static void main(String[] args)
{
Set<String> strings = new HashSet<String>();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
strings.add("five");
Set<String> test = new HashSet<String>();
System.out.println("Code "+test.hashCode());
for (String s : strings) {
test.add(s);
System.out.println("Code "+test.hashCode());
}
}
}
Code 0
Code 115276
Code 3258622
Code 3368804
Code 113708290
Code 116857384