2016-12-22 106 views
6

在下面的代碼中,我期望equals()返回true,但它不會。我在這裏錯過了什麼?SparseBooleanArray.equals()未按預期工作

SparseBooleanArray array_0 = new SparseBooleanArray(); 
    array_0.put(0, true); 
    array_0.put(2, true); 

    SparseBooleanArray array_1 = new SparseBooleanArray(); 
    array_1.put(0, true); 
    array_1.put(2, true); 

    boolean isEqual = array_0.equals(array_1); // is false instead of true 

看在調試器都陣列,他們似乎同樣給​​我(他們有不同的shadow$_monitor_價值,但我不知道那是什麼應該是)。 toString()方法也返回相同的字符串。

我想寫一個函數的單元測試,將EnumSet轉換爲SparseBooleanArray,但我無法手動創建相同的數組以將其與函數的返回值進行比較。


編輯

我還要提到的是hasCode()返回的值不同,以及,這不應該的基礎上,documentation

+0

這很奇怪。我可以重現你的發現,但源代碼看起來應該匹配... – CommonsWare

+1

你在測試它的哪個版本的android? – Blackbelt

+0

@Blackbelt在Android 6.0 API 23 - x86_64仿真器 – rozina

回答

0

查看源代碼,無論是equalshashCode方法不爲SparseBooleanArraySparseIntArraySparseLongArraySparseArray實施。我想說這是一個重要的缺失功能,應該向Google報告。

總之,我使用很長一段時間,這些實用的方法來解決這個問題:

public static boolean equals(SparseArray arrayOne, SparseArray arrayTwo){ 
    if(arrayOne == arrayTwo){ 
     return true; 
    } else if(arrayOne.size() != arrayTwo.size()){ 
     return false; 
    } 
    for(int i = 0; i < arrayOne.size(); i++){ 
     if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){ 
      return false; 
     } 
     final Object valueOne = arrayOne.valueAt(i); 
     final Object valueTwo = arrayTwo.valueAt(i); 
     if(valueOne != null && !valueOne.equals(valueTwo)){ 
      return false; 
     } else if(valueTwo != null && !valueTwo.equals(valueOne)){ 
      return false; 
     } 
    } 
    return true; 
} 

public static boolean equals(SparseBooleanArray arrayOne, SparseBooleanArray arrayTwo){ 
    if(arrayOne == arrayTwo){ 
     return true; 
    } else if(arrayOne.size() != arrayTwo.size()){ 
     return false; 
    } 
    for(int i = 0; i < arrayOne.size(); i++){ 
     if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){ 
      return false; 
     } else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){ 
      return false; 
     } 
    } 
    return true; 
} 

public static boolean equals(SparseIntArray arrayOne, SparseIntArray arrayTwo){ 
    if(arrayOne == arrayTwo){ 
     return true; 
    } else if(arrayOne.size() != arrayTwo.size()){ 
     return false; 
    } 
    for(int i = 0; i < arrayOne.size(); i++){ 
     if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){ 
      return false; 
     } else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){ 
      return false; 
     } 
    } 
    return true; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public static boolean equals(SparseLongArray arrayOne, SparseLongArray arrayTwo){ 
    if(arrayOne == arrayTwo){ 
     return true; 
    } else if(arrayOne.size() != arrayTwo.size()){ 
     return false; 
    } 
    for(int i = 0; i < arrayOne.size(); i++){ 
     if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){ 
      return false; 
     } else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){ 
      return false; 
     } 
    } 
    return true; 
} 

然而,也有可能(如在評論中提到的),並且可能更好,子類SparseArray類覆蓋equalshashCode方法。

免責聲明:我沒有測試hashCodeequals執行下面提供的代碼,請寫一些自己的測試,以確保它正常工作。 #DontTrustTheInternet

public class SparseBooleanArray extends android.util.SparseBooleanArray { 

    @Override 
    public boolean equals(Object o) { 
     if(!(o instanceof SparseBooleanArray)){ 
      return false; 
     } else if(this == o){ 
      return true; 
     } 
     final SparseBooleanArray other = (SparseBooleanArray) o; 
     if(size() != other.size()){ 
      return false; 
     } 
     for(int i = 0; i < size(); i++){ 
      if(keyAt(i) != other.keyAt(i)){ 
       return false; 
      } else if(valueAt(i) != other.valueAt(i)){ 
       return false; 
      } 
     } 
     return true; 
    } 

    @Override 
    public int hashCode() { 
     int result = 17; 
     for(int i = 0; i < size(); i++){ 
      result = 31 * result + keyAt(i); 
      result = 31 * result + (valueAt(i)?1:0); 
     } 
     return result; 
    } 
}