Java提高篇(三八)-----Java集合細節(四):保持compareTo和equals同步


在Java中我們常使用Comparable接口來實現排序,其中compareTo是實現該接口方法。我們知道compareTo返回0表示兩個對象相等,返回正數表示大於,返回負數表示小於。同時我們也知道equals也可以判斷兩個對象是否相等,那么他們兩者之間是否存在關聯關系呢?

public class Student implements Comparable<Student>{
    private String id;
    private String name;
    private int age;
</span><span style="color: #0000ff">public</span> Student(String id,String name,<span style="color: #0000ff">int</span><span style="color: #000000"> age){
    </span><span style="color: #0000ff">this</span>.id =<span style="color: #000000"> id;
    </span><span style="color: #0000ff">this</span>.name =<span style="color: #000000"> name;
    </span><span style="color: #0000ff">this</span>.age =<span style="color: #000000"> age;
}

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">boolean</span><span style="color: #000000"> equals(Object obj){
    </span><span style="color: #0000ff">if</span>(obj == <span style="color: #0000ff">null</span><span style="color: #000000">){
        </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
    }
    
    </span><span style="color: #0000ff">if</span>(<span style="color: #0000ff">this</span> ==<span style="color: #000000"> obj){
        </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
    }
    
    </span><span style="color: #0000ff">if</span>(obj.getClass() != <span style="color: #0000ff">this</span><span style="color: #000000">.getClass()){
        </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
    }
    
    Student student </span>=<span style="color: #000000"> (Student)obj;
    </span><span style="color: #0000ff">if</span>(!<span style="color: #000000">student.getName().equals(getName())){
        </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
    }
    
    </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
}

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span><span style="color: #000000"> compareTo(Student student) {
    </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">this</span>.age -<span style="color: #000000"> student.age;
}

</span><span style="color: #008000">/**</span><span style="color: #008000"> 省略getter、setter方法 </span><span style="color: #008000">*/</span><span style="color: #000000">

}

Student類實現Comparable接口和實現equals方法,其中compareTo是根據age來比對的,equals是根據name來比對的。

public static void main(String[] args){
        List<Student> list = new ArrayList<>();
        list.add(new Student("1", "chenssy1", 24));
        list.add(new Student("2", "chenssy1", 26));
    Collections.sort(list);   </span><span style="color: #008000">//</span><span style="color: #008000">排序</span>
Student student = new Student("2", "chenssy1", 26);
    </span><span style="color: #008000">//</span><span style="color: #008000">檢索student在list中的位置</span>
    <span style="color: #0000ff">int</span> index1 =<span style="color: #000000"> list.indexOf(student);
    </span><span style="color: #0000ff">int</span> index2 =<span style="color: #000000"> Collections.binarySearch(list, student);
    
    System.out.println(</span>&quot;index1 = &quot; +<span style="color: #000000"> index1);
    System.out.println(</span>&quot;index2 = &quot; +<span style="color: #000000"> index2);
}</span></pre>

按照常規思路來說應該兩者index是一致的,因為他們檢索的是同一個對象,但是非常遺憾,其運行結果:

index1 = 0
index2 = 1

為什么會產生這樣不同的結果呢?這是因為indexOf和binarySearch的實現機制不同,indexOf是基於equals來實現的只要equals返回TRUE就認為已經找到了相同的元素。而binarySearch是基於compareTo方法的,當compareTo返回0 時就認為已經找到了該元素。在我們實現的Student類中我們覆寫了compareTo和equals方法,但是我們的compareTo、equals的比較依據不同,一個是基於age、一個是基於name。比較依據不同那么得到的結果很有可能會不同。所以知道了原因,我們就好修改了:將兩者之間的比較依據保持一致即可。

對於compareTo和equals兩個方法我們可以總結為:compareTo是判斷元素在排序中的位置是否相等,equals是判斷元素是否相等,既然一個決定排序位置,一個決定相等,所以我們非常有必要確保當排序位置相同時,其equals也應該相等。

細節(4.1):實現了compareTo方法,就有必要實現equals方法,同時還需要確保兩個方法同步。

 

參考文獻:編寫高質量代碼:改善Java程序的151個建議


-----原文出自:http://cmsblogs.com/?p=1242,請尊重作者辛勤勞動成果,轉載說明出處.

-----個人站點:http://cmsblogs.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM