请参阅下面的junit测试代码段。帐户有一个带有分配的集合。当包含的城市名称等于'Bladel'
时,我想从赋值中删除一个元素Assignment toBeDeleted = null;
for (Assignment ass : account.getAssignments()) {
if (ass.getCity().getName().equals("Bladel")) {
toBeDeleted = ass;
break;
}
}
Assert.assertNotNull(toBeDeleted);
for (Assignment ass : account.getAssignments()) {
logger.info(String.format("hash [%s] %d with [%s] %d",toBeDeleted.getCity().getName(), toBeDeleted.hashCode(), ass.getCity().getName(), ass.hashCode()));
if (ass.equals(toBeDeleted)) {logger.info("found equal assignment"); }
if (ass.hashCode() == toBeDeleted.hashCode()) {logger.info("found equal hash assignment"); }
if (ass == toBeDeleted) { logger.info("it is == with"); }
}
Assert.assertTrue(account.getAssignments().contains(toBeDeleted));
但是失败了所以我用.remove()
Stil取代.contains()
失败了。该日志明确显示toBeDeleted在某个时刻等于集合中的元素:
2014-02-27 22:33:35 INFO AssignmentDAOTest:134 - found equal assignment
2014-02-27 22:33:35 INFO Assignment:66 - for assignment + Bladel result is 2121952
2014-02-27 22:33:35 INFO Assignment:66 - for assignment + Bladel result is 2121952
2014-02-27 22:33:35 INFO AssignmentDAOTest:135 - found equal hash assignment
2014-02-27 22:33:35 INFO AssignmentDAOTest:136 - it is == with
出了什么问题?当remove()
返回true时,我认为contains()
和equals()
匹配。
每条评论: Account是Hibernate映射的java类,集合的总体是在单元测试中留给Hibernate。
public class Account {
....
@OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade={CascadeType.ALL})
public Set<Assignment> getAssignments() {return assignments;}
public void setAssignments(Set<Assignment> asgmnts) {
logger.info("setting assignments");
assignments = asgmnts;
}
答案 0 :(得分:1)
如果您使用TreeSet存储分配,则需要覆盖Assignment类中的compareTo()方法,或者提供自定义比较器以比较Assignment对象。
以下是来自javadoc的文字:link
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。集合的行为即使其排序与equals不一致也是明确定义的;它只是没有遵守Set接口的一般合同。