2011-11-26 87 views
1

我有兩個DTO需要使用(Arrays.equals)進行比較,它們永遠不會等於。在我查看每個屬性時,兩個DTO中的數據都是相等的,有時候它的長度等於,但Arrays.equals返回false,我嘗試使用Arrays.deepEquals,但存在相同的問題,但在某些字段中。我在調試時發現了一些問題:兩個dto的java字節數組比較使用Arrays.equals

1-在兩個DTO中,hashcode方法都不一樣。
2-字符串類型屬性中的問題。

我的問題是我如何測試和檢測哪些屬性是不同的。

這裏是我的代碼卡:

Boolean isEqual = false; 
    ByteArrayOutputStream bStream = new ByteArrayOutputStream(); 
    ObjectOutputStream oStream; 

    ByteArrayOutputStream bStream2 = new ByteArrayOutputStream(); 
    ObjectOutputStream oStream2; 

    try { 
     oStream = new ObjectOutputStream(bStream); 
     oStream.writeObject(obj1); 
     byte[] obj1ByteArray = bStream.toByteArray(); 

     oStream2 = new ObjectOutputStream(bStream2); 
     oStream2.writeObject(obj2); 
     byte[] obj2ByteArray = bStream2.toByteArray(); 
     System.out.println("Obj1>>" + obj1ByteArray.length); 
     System.out.println("Obj2>>" + obj2ByteArray.length); 
     isEqual = Arrays.equals(obj1ByteArray, obj2ByteArray); 

     oStream.close(); 
     oStream2.close(); 

數據卡:

Length 
Obj1>>709 
Obj2>>709 
------------------------------------------------ 
Object 1 
com[email protected]1ab5140 
59 
test_job_5555555 
-100 
59 
1 
وظيفة تجريبية 6 
وظيفة تجريبية 6أخري 
10 
10 
10.0 
وظيفة تجريبية الغرض من الوظيفة 6 

-------------------------------- 
Object 2 
com[email protected]4cfc52 
59 
test_job_5555555 
0 
59 
1 
وظيفة تجريبية 6 
وظيفة تجريبية 6أخري 
10 
10 
10.0 
وظيفة تجريبية الغرض من الوظيفة 6 

謝謝。

+0

您的兩個_JobDTO_對象:_obj1_和_obj2_根據您提供的輸出不相等,因爲_they包含不同的data_。如果您想要了解更多幫助,請發佈您的_JobDTO_類的_hashCode_和_equals_實現。不知道這些_JobDTOs_有什麼樣的屬性/屬性比我已經(嘗試)提供的幫助更難。 –

回答

0

Arrays.equals(byte[],byte[]) documentation指出:

兩個陣列被認爲是相等的,如果兩個陣列包含相同數量的元件,並且在這兩個陣列元件的所有相應對是相等的。換句話說,如果兩個數組按照相同的順序包含相同的元素,則它們是相等的

所以,如果你希望他們包含一些差異,你將不能夠兩者成功比較你的字節數組。

如果你沒有(或不想)控制你的對象如何被序列化,那麼你可以使用某種Comparator<byte[]>

public final class MyComparator implements Comparator<byte[]> { 

    private static final int ATTR_START = 0; 
    private static final int ATTR_END = 7; 

    @Override 
    public int compare(byte[] left, byte[] right) { 
    if (left.length != right.length) 
     return left.length - right.length; 

    byte[] leftAttr = Arrays.copyOfRange(left, ATTR_START, ATTR_END); 
    byte[] rightAttr = Arrays.copyOfRange(left, ATTR_START, ATTR_END); 

    return Arrays.equals(leftAttr, rightAttr) ? 0 : -1; 
    } 
} 

我意識到這是有點狡猾,所以這裏是另一個問題。

public final class MyByteArrayOutputStream extends ByteArrayOutputStream { 

    private static final int ATTR_START = 0; 
    private static final int ATTR_END = 7; 

    @Override 
    public int hashCode() { 
    // this can be implemented based on *your* attribute/attributes 
    // and its/their location in the buffer too, like in equals just below 
    return Arrays.hashCode(buf); 
    } 

    @Override 
    public boolean equals(Object object) { 
    boolean equals = false; 
    if (object instanceof MyByteArrayOutputStream) { 
     MyByteArrayOutputStream other = (MyByteArrayOutputStream) object; 
     byte[] thisAttr = Arrays.copyOfRange(buf, ATTR_START, ATTR_END); 
     byte[] otherAttr = Arrays.copyOfRange(other.buf, ATTR_START, ATTR_END); 

     if (Arrays.equals(thisAttr, otherAttr)) { 
     byte[] thisRest = Arrays.copyOfRange(buf, ATTR_END, buf.length); 
     byte[] otherRest = Arrays.copyOfRange(other.buf, ATTR_END, buf.length); 

     equals = Arrays.equals(thisRest, otherRest); 
     } 
    } 
    return equals; 
    } 
} 

子類ByteArrayOutputStream並實現自定義的邏輯相等。

+0

「如果兩個數組按照相同的順序包含相同的元素,則它們是相等的。」他們的意思是「相同順序的相同元素」。它們是否意味着數據如果是的話我對這兩個DTO使用相同的值 –

+0

@SherifOmar這意味着如果您有兩個字節數組_a_和_b_,則_Arrays.equals(a,b)_只會返回_true_ iff:a.length == b.length _and_ a [i] == b [i]其中_i = 0,1,..,a.length - 1_。也就是說,如果兩個數組在每個索引處包含相同的字節值。 –

0

一些言論,但不是sollution:

  • 出乎你的問題的標題不是Arrays.equals是你的問題,但的ObjectOutputStream輸出。即使這可能不是真的 - 它可能是一個Unicode編碼問題(見下文)。

  • 請提供short, self contained and correct example。您的代碼錯過了真實的輸入數據。這是與下一點加起來:

  • StackOverflow的大多數讀者不能做西班牙語,法語,德語...腳本偶爾的特殊字符。別說完整的阿拉伯文字。這大大減少了想要考慮你的問題的人數。

最後是問題本身:由於Unicode允許字符組合的方式,可以以相同方式顯示兩個不同的Unicode字符串。所以一般的建議是:儘可能地減少你的問題。

  • 比較每個字符串對在你DTO的String.equals
  • 每一對返回false但以相同方式顯示的每一對必須進一步檢查:使用NFCNFKC將它們送到java.text.Normailzer並再次比較結果。
  • 如果結果現在做比較,您有Unicode編碼問題。寫下你的結果,準備一個new exampls並挖掘這個網站與新的搜索短語。

如果此過程無法解決您的問題或縮小您的問題範圍,請通過編輯您的問題來提供檢查結果。

哦,我差點忘了:你說

我有兩個DTO需要使用進行比較......

你應該想想你真正想實現和然後決定如何來做到這一點。如果要比較字節,請使用Arrays.equals。如果您想比較DTO,則可以通過比較DTO中的每個字段進行任何奇特的「規範化」來構建自己的比較方法。一個工具來幫助你可能是Apache EqualsBuilder

+0

感謝您的建議,其實我使用比較這些DTOs的解決方案(這並不意味着我贊同,我建議使用比較DTO),只有我的屏幕有這種行爲,所以我試圖找出在哪裏問題,甚至如何調試以找出問題,您注意到它可能是(ObjectOutputStream或Unicode),我嘗試通過屬性的值進行比較,並且它運行良好,但此解決方案拒絕,我必須使用字節數組比較。 –