简体   繁体   English

使用 Jackson 和 Spring 将 JavaScript 数组反序列化为 Java LinkedHashSet 不会删除重复项

[英]Deserialization of JavaScript array to Java LinkedHashSet using Jackson and Spring doesn't remove duplicates

Let's say I have this client-side JSON input:假设我有这个客户端 JSON 输入:

{
   id: "5",
   types: [
      {id: "1", types:[]},
      {id: "2", types:[]},
      {id: "1", types[]}
   ]
}

I have this class:我有这门课:

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());
    }
}

I have this Java Spring endpoint where I pass the input in the body of a POST request:我有这个 Java Spring 端点,我在其中传递POST请求正文中的输入:

@RequestMapping(value = "api/entity", method = RequestMethod.POST)
public Entity createEntity(@RequestBody final Entity in) {
    Set<Entity> types = in.getTypes();
    [...]
}

I would like in:我想在:

Set<Entity> types = in.getTypes();

to have only two entries in the correct order... since one of them is a duplicate based on the id... Instead I get duplicates in the LinkedHashSet (!)以正确的顺序只有两个条目...因为其中一个是基于 id 的重复项...相反,我在 LinkedHashSet (!)

I thought from the code I have that removing duplicates would work automatically, but apparently it is not.我从我拥有的代码中认为删除重复项会自动工作,但显然不是。

This question has a broader context than Why do I need to override the equals and hashCode methods in Java?这个问题比为什么我需要覆盖 Java 中的 equals 和 hashCode 方法有更广泛的背景 since it is using implicit Jackson serialization through Java Spring.因为它通过 Java Spring 使用隐式 Jackson 序列化。

Only overriding equals method will not work because hash-based collections use both the equals and hashCode method to see if two objects are the same.仅覆盖equals方法将不起作用,因为基于哈希的集合同时使用equalshashCode方法来查看两个对象是否相同。 You'll need to override hashCode() method in Entity class as both hashCode() and equals() method are required to be properly implemented to work with Hash based collections.你需要重写hashCode()的方法Entity类既是hashCode()equals()需要的方法来正确地实现工作与基于散列的集合。

If your requirement is that if the some or all of the fields of two objects of the Entity class are same, then the two objects are to be considered equivalent, in that case, you'll have to override both equals() and hashCode() method.如果您的要求是,如果Entity类的两个对象的部分或全部字段相同,那么这两个对象将被视为等效,在这种情况下,您必须同时覆盖equals()hashCode()方法。

For eg - if only id field in the Entity class is required to determine if the two objects are equal, then you'll override equals() , something like this:例如 - 如果只需要实体类中的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;

}

but along with it, the hashCode() method need to be overridden in a way to produce same hashcode if id has the same value, maybe something like this:但与此同时,如果 id 具有相同的值,则需要以某种方式覆盖hashCode()方法以生成相同的哈希码,可能是这样的:

@Override
public int hashCode() {
    int h = 17;
    h = h * 31 + id == null ? 0 : id.hashCode();
    return h;
}

Only now it'll work properly with Hash based collections, as both these methods are used to identify an object uniquely.只有现在它才能与基于 Hash 的集合一起正常工作,因为这两种方法都用于唯一标识对象。


More on this:更多关于这个:

Assuming that if the members of Entity class ie the id and type are same then the object of class Entity is same is completely wrong unless and until you override the hashcode() and equals() function explicitly.假设如果Entity类的成员,即idtype相同,那么类Entity的对象相同是完全错误的,除非并且直到您显式覆盖hashcode()equals()函数。

If you do not override the hashCode() and equals() function in your Entity class then the two objects will be different even though they have same data within their members.如果您不覆盖Entity类中的hashCode()equals()函数,则这两个对象将不同,即使它们的成员中具有相同的数据。

In Java, objects equality is determined by overriding the equals() and hashcode() contract .在 Java 中,对象相等性是通过覆盖equals()hashcode() 合同来确定的

There are default implementations of equals() and hashCode() in Object. Object 中有equals()hashCode()默认实现。 If you don't provide your own implementation, those will be used.如果您不提供自己的实现,则将使用这些实现。 For equals() , this means an == comparison: the objects will only be equal if they are exactly the same object.对于equals() ,这意味着==比较:只有当它们是完全相同的对象时,对象才会相等。

Answer to your question : Objects in LinkedHashSet are inheriting default behaviour of equals() and hashcode() methods from Object class.回答您的问题LinkedHashSet中的对象从Object类继承equals()hashcode()方法的默认行为。 Override equals() and hashcode() of Entity class of LinkedHashSet覆盖LinkedHashSet Entity类的equals()hashcode()

See below this for default behaviour of hashcode() and equals() .见下面这个为默认行为hashcode()equals()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM