2016-05-29 40 views
3

我有一個Class持有使用自它的對象引用忽略equals對於自參照親子對象

public class MyObject { 

    private String name; 

    private List<MyObject> childrens; 

    private MyObject parent; 

    @Override 
    public int hashCode() { 
     int hash = 5; 
     hash = 13 * hash + Objects.hashCode(this.name); 
     hash = 13 * hash + Objects.hashCode(this.childrens); 
     hash = 13 * hash + Objects.hashCode(this.parent); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final MyObject other = (MyObject) obj; 

     if(!this.name.equalsIgnoreCase(other.name)) 
      return false; 

     if(this.parent==null) 
     { 
      if(other.parent!=null) 
      { 
       return false; 
      } 
     }else if(!this.parent.equals(other.parent)) 
     { 
      return false; 
     } 
     if(!allChildrenEqual(this,other)) 
     { 
      return false; 
     } 
     return true; 
    } 

    private boolean allChildrenEqual(MyObject aThis, MyObject other) { 
     List<MyObject> children1=aThis.getChildrens(); 
     List<MyObject> children2=other.getChildrens(); 

     //Avoid infinite recusion can't use anything simple as 
     // list1 equals other list 
     return true; 
    } 

我想知道我怎麼能覆蓋中父子關係等於正常與之相比的層次這些對象沒有進入無限遞歸併導致StackOverflowError

我有一種感覺,我失去了一些真正明顯的東西。 在此先感謝。

+0

父母總是非空(對於頂部元素?)。否則,你的代碼在檢查孩子之前會返回false或者拋出NPE。 – Codebender

+0

@Codebender對不起,我的錯誤錯過了代碼片段中的條件。編輯它 –

+1

如果您使用'equalsIgnoreCase'來比較名稱,那麼您需要'name'字段的散列也不區分大小寫,否則您的破解散列實現。 – khelwood

回答

1

創建一個equalsNoParentCheck()方法,然後使用allChildrenEqual()方法中的方法,並將equals()方法更改爲使用equalsNoParentCheck()並執行父級檢查。

此外,您在hashCode()方法中具有相同的遞歸問題。只需從散列碼算法中刪除父項即可。哈希碼不要是唯一的,只需盡最大的努力。無論如何,包括父母在內的總體上不太可能會產生很大的變化。

由於您使用Objects.hashCode(),你還不如用Objects.hash()

@Override 
public int hashCode() { 
    return Objects.hash(this.name, this.childrens); // Don't hash this.parent 
} 
+0

那麼該方法的實施將會只比較當前的水平和兒童而不是父母嗎? –

+0

除了比較'parent'外,它會執行'equals()'所做的所有操作。 [DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)原理然後說從[equals()'中移除該通用邏輯,並讓equals()調用新的equalsNoParentCheck() ,除了做父母檢查本身。是否在'equals()'中檢查+類型並將參數設置爲'equalsNoParentCheck()'實際的MyObject類型。 – Andreas

0

我認爲僅僅把「遞歸等效試驗的基本情況」,也就是

if (object == this) 
    return true; 
在equals()定義的第一行中的

將防止無限遞歸。