Java:TreeSet 的问题
我有一堂Odp课。我想使用 TreeSet 来保存 Odp 对象的排序集合。但是,我一直遇到问题。
public class OdpStorage {
private TreeSet<Odp> collection = new TreeSet<Odp>();
public addOdp(Odp o) {
return collection.add(o);
}
public int size() {
return collection.size();
}
}
如果 collection.add(Odp o) 已经在树中,那么它应该不执行任何操作,对吗?不知何故,这个单元测试失败了:
OdpStorage ts = new OdpStorage();
Odp ftw = new Odp("LOL");
Odp ktr = new Odp("OMG");
ts.addOdp(ftw);
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ktr);
assertEquals(2, ts.size());
断言失败。它期望 2,但返回值是 5。为什么? odp.equals() 函数会搞砸吗?
同样,调用 collection.contains(o)
也会失败,即使集合 X
中有一个对象 o.equals(X)
也是如此> 返回真。
Odp 的 .equals() 函数:(由 Eclipse 生成)
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Odp))
return false;
Gene other = (Odp) obj;
if (sequence == null) {
if (other.sequence != null)
return false;
} else if (!sequence.equals(other.sequence))
return false;
return true;
}
compareTo:
/**
* this = g0
* if they are equal, g1 is presumed to come first
*
* @return -1 if g0 comes before g1; 1 if g0 comes after g1
*/
@Override
public int compareTo(Odp g1) {
if (sequence.length() < g1.getSeq().length()) {
return -1;
}
else if (sequence.length() > g1.getSeq().length()) {
return 1;
}
if (sequence.compareTo(g1.getSeq()) < 0) {
return -1;
}
return 1;
}
hashCode()
未被覆盖。问题?
更新 hashCode()
如下:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((sequence == null) ? 0 : sequence.hashCode());
return result;
}
但这仍然不能解决问题。
I have a class Odp. I want to use TreeSet to keep a sorted collection of Odp objects. However, I've been having problems.
public class OdpStorage {
private TreeSet<Odp> collection = new TreeSet<Odp>();
public addOdp(Odp o) {
return collection.add(o);
}
public int size() {
return collection.size();
}
}
collection.add(Odp o) is supposed to do nothing if it's already in the tree, right? Somehow, this unit test fails:
OdpStorage ts = new OdpStorage();
Odp ftw = new Odp("LOL");
Odp ktr = new Odp("OMG");
ts.addOdp(ftw);
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ktr);
assertEquals(2, ts.size());
The assertion fails. It expects 2, but the return value is 5. Why? Could the odp.equals() function be messed up?
Similarly, calling collection.contains(o)
fails, even when the there is an object in the set X
for which o.equals(X)
returns true.
The .equals() function of Odp: (generated by Eclipse)
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Odp))
return false;
Gene other = (Odp) obj;
if (sequence == null) {
if (other.sequence != null)
return false;
} else if (!sequence.equals(other.sequence))
return false;
return true;
}
compareTo:
/**
* this = g0
* if they are equal, g1 is presumed to come first
*
* @return -1 if g0 comes before g1; 1 if g0 comes after g1
*/
@Override
public int compareTo(Odp g1) {
if (sequence.length() < g1.getSeq().length()) {
return -1;
}
else if (sequence.length() > g1.getSeq().length()) {
return 1;
}
if (sequence.compareTo(g1.getSeq()) < 0) {
return -1;
}
return 1;
}
hashCode()
is not overridden. Problem?
UPDATEhashCode()
is as follows:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((sequence == null) ? 0 : sequence.hashCode());
return result;
}
But that still doesn't solve the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的
compareTo
实现永远不会返回 0。当对象实例相等时,它应该返回 0。Your
compareTo
implementation never returns 0. It should return 0 when the object instances are equal.您的
collection.add(o)
似乎无法在支持的TreeMap
中找到该对象。您的Odp
是否实现了Comparable
,或者您是否在TreeSet
上设置了默认的Comparable
,其compare 你已经实现的方法?如果是这样,您需要确保您的
compareTo
(对于Comparable
)或您的Comparator
compare
方法如果传入的对象等于
,则返回0
。编辑(回应您对原始帖子的评论):
建议 每当您重写
equals()
EDIT2 以响应您的
compareTo
实现时,您都会重写HashCode()
:如果
g0
和g1
相等,你应该返回0。这就是问题的根源。It appears that your
collection.add(o)
is failing to find the object in the backingTreeMap
. Does yourOdp
implementComparable
or are you setting a defaultComparable
on yourTreeSet
whosecompare
method you have implemented? If so, you will need to ensure that yourcompareTo
(for theComparable
), or yourComparator
compare
method will return0
if the objects passed in areequals
.EDIT (in response to your comment to the original post):
It is recommended that you override
HashCode()
whenever you overrideequals()
EDIT2 in response to your
compareTo
implementation:If
g0
andg1
are equal, you should return 0. This is the root of the problem.配合清理你的平等者,它有太多的 if/else。用带有大量条件测试的漂亮 do/while 替换它。如果所有测试都通过,则 reutrn true...是的,它有“goto”语句,但它非常易于阅读,甚至更容易根据需要插入新条件,而无需大量嵌套。嵌套 if/else 是邪恶的。使用“else”是邪恶的,而且几乎总是不需要的。
Mate cleanup your equals, its got too many if/elses. replace it with a nice do/while with lots of condition tests. If all the tests pass then reutrn true...Yes its got "goto" statements but its very easy to read and even easier to insert new conditions as necessary without lots of nesting. Nesting if/elses is evil. Using "elses" is evil and almost always never needed.