假设我有此客户端JSON输入:
{
id: "5",
types: [
{id: "1", types:[]},
{id: "2", types:[]},
{id: "1", types[]}
]
}
我有这个课:
class Entity {
private String id;
private Set<Entity> types = new LinkedHashSet<>();
public String getId() {
return this.id;
}
public String setId(String id) {
this.id = id;
}
public Set<Entity> getTypes() {
return types;
}
@JsonDeserialize(as=LinkedHashSet.class)
public void setTypes(Set<Entity> types) {
this.types = types;
}
@Override
public boolean equals(Object o){
if (o == null || !(o instanceof Entity)){
return false;
}
return this.getId().equals(((Entity)o).getId());
}
}
我有这个java弹簧端点,我在邮政请求的正文中传递输入:
@RequestMapping(value = "api/entity", method = RequestMethod.POST)
public Entity createEntity(@RequestBody final Entity in) {
Set<Entity> types = in.getTypes();
[...]
}
我想要:
Set<Entity> types = in.getTypes();
只有两个条目以正确的顺序...因为其中一个是基于ID的重复。相反,我在linkedhashset(!)
中获得了重复。我从我的代码中认为,删除重复项会自动工作,但显然不是。
这个问题比更广泛的上下文,为什么我需要覆盖Java中的等值和哈希码方法?由于它正在使用隐式杰克逊通过Java Spring序列化。
仅覆盖equals
方法将无效,因为基于哈希的集合使用equals
和hashCode
方法来查看两个对象是否相同。您需要在Entity
类中覆盖hashCode()
方法,因为hashCode()
和equals()
方法都必须正确实现以使用基于哈希的集合。
如果您的要求是,如果Entity
类的两个对象的某些字段相同,则两个对象应视为等效,在这种情况下,您必须同时覆盖equals()
和hashCode()
方法。
例如 - 如果需要实体类中的id
字段才能确定两个对象是否相等,则您将覆盖equals()
,类似的内容:
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o instanceof Entity){
Entity that = (Entity) o;
return this.id == null ? that.id == null : this.id.equals(that.id);
}
return false;
}
但随之而来的是,如果ID具有相同的值,则需要以产生相同的主题的方式覆盖hashCode()
方法:
@Override
public int hashCode() {
int h = 17;
h = h * 31 + id == null ? 0 : id.hashCode();
return h;
}
现在,它才能与基于哈希的集合正常使用,因为这两种方法都用于唯一识别对象。
有关此的更多信息:
- java中的hashcode和equals方法之间的关系
- 为什么我需要覆盖Java中的等效方法?
假设如果Entity
类的成员即id
和type
是相同的,那么Entity
类的对象是完全错误的,除非并且直到您覆盖hashcode()
和equals()
函数,否则明确。/p>
如果您不覆盖hashCode()
中的CC_21和equals()
函数,那么即使它们在成员中具有相同的数据,这两个对象也会有所不同。
在java中,对象平等是通过覆盖equals()
和hashcode()
合同来确定的。
对象中有equals()
和hashCode()
的默认实现。如果您不提供自己的实施,则将使用这些实施。对于equals()
,这意味着==
比较:仅当对象完全是同一对象时。
回答您的问题:LinkedHashSet
中的对象是从Object
类继承equals()
和hashcode()
方法的默认行为。Entity
LinkedHashSet
类的覆盖equals()
和hashcode()
hashcode()
和equals()
的默认行为请参见下面。