2016-12-31 16 views
10

Hãy nói rằng tôi có client-side JSON này đầu vào:Deserialization của mảng hoạt Javascript để Java LinkedHashSet sử dụng Jackson và mùa xuân không loại bỏ bản sao

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

Tôi có lớp này:

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

tôi có điểm cuối Java Spring này, nơi tôi chuyển đầu vào trong phần nội dung của một yêu cầu POST:

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

Tôi muốn ở:

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

chỉ có hai mục theo đúng thứ tự ... kể từ khi một trong số họ là một bản sao dựa trên id ... Thay vào đó tôi nhận được bản sao trong LinkedHashSet (!)

Tôi nghĩ từ mã mà tôi có mà loại bỏ các bản sao sẽ làm việc tự động, nhưng dường như nó không phải là.

Câu hỏi này có ngữ cảnh rộng hơn Why do I need to override the equals and hashCode methods in Java? vì nó đang sử dụng tuần tự hóa Jackson ngầm qua Java Spring.

+3

Hàm băm() của bạn ở đâu? – GurV

+1

Đó là một phần của hợp đồng giống như 'bằng (đối tượng)'. – GurV

+1

Cảm ơn! có vẻ như tôi đang thiếu điều đó - hãy để tôi thêm nó và xem nó hoạt động như thế nào –

Trả lời

6

Chỉ ghi đè phương pháp equals sẽ không hoạt động vì bộ sưu tập dựa trên băm sử dụng cả phương pháp equalshashCode để xem hai đối tượng có giống nhau không. Bạn sẽ cần ghi đè phương thức hashCode() trong lớp Entity vì cả hai phương pháp hashCode()equals() được yêu cầu phải được triển khai đúng để làm việc với các bộ sưu tập dựa trên Hash.

Nếu yêu cầu của bạn là nếu một số hoặc tất cả các trường của hai đối tượng trong lớp Entity giống nhau, thì hai đối tượng sẽ được coi là tương đương, trong trường hợp đó, bạn sẽ phải ghi đè cả equals() và Phương pháp hashCode().

Ví dụ: - nếu chỉ id lĩnh vực trong lớp Entity là cần thiết để xác định xem hai đối tượng đều bình đẳng, sau đó bạn sẽ ghi đè equals(), một cái gì đó như thế này:

@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; 

} 

nhưng cùng với nó, phương pháp hashCode() cần phải được ghi đè một cách để tạo ra cùng một hashcode nếu id có giá trị như nhau, có lẽ một cái gì đó như thế này:

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

Chỉ bây giờ nó sẽ hoạt động đúng với các bộ sưu tập Hash dựa, vì cả hai phương pháp này được sử dụng để xác định một đối tượng duy nhất.


Thông tin thêm về điều này:

3

Giả sử rằng nếu các thành viên của Entity lớp ví dụ:idtype giống nhau thì đối tượng của lớp Entity giống nhau hoàn toàn sai trừ khi và cho đến khi bạn ghi đè hàm hashcode()equals() một cách rõ ràng.

Nếu bạn không ghi đè hàm hashCode()equals() trong lớp Entity thì hai đối tượng sẽ khác nhau mặc dù chúng có cùng dữ liệu trong các thành viên của chúng.

+1

Tôi quên '' 'hashCode()' '' - Tôi nghĩ rằng các bộ sưu tập dựa trên băm đã sử dụng '' 'equals()' '' để xác định xem nó là cùng một đối tượng .. –

+1

@MichailMichailidis Bạn nên luôn cân nhắc việc ghi đè cả 'hashCode()' cũng như 'equals()' và không chỉ là một. Tôi hy vọng điều này giải quyết vấn đề của bạn :) – user2004685

+1

yeap tôi đã tìm ra dựa trên câu trả lời của Gurwinder đã đến sớm hơn một chút :) Cảm ơn –

3

Trong Java, đối tượng bình đẳng được xác định bằng cách ghi đè equals()hashcode()contract.

Có các triển khai mặc định là equals()hashCode() trong Đối tượng. Nếu bạn không cung cấp việc triển khai của riêng mình, chúng sẽ được sử dụng. Đối với equals(), điều này có nghĩa là so sánh ==: các đối tượng sẽ chỉ bằng nhau nếu chúng chính xác là cùng một đối tượng.

trả lời cho câu hỏi của bạn: Objects trong LinkedHashSet được kế thừa hành vi mặc định của eqauls()hashcode() phương pháp từ Object lớp. Override eqauls()hashcode() của Entity lớp LinkedHashSet

Xem dưới đây this cho hành vi mặc định của hashcode()equals().

Các vấn đề liên quan