在Java中我们常使用Comparable接口来实现排序,其中compareTo是实现该接口方法。我们知道compareTo返回0表示两个对象相等,返回正数表示大于,返回负数表示小于。同时我们也知道equals也可以判断两个对象是否相等,那么他们两者之间是否存在关联关系呢?

  1. public class Student implements Comparable<Student>{
  2. private String id;
  3. private String name;
  4. private int age;
  5. </span><span style="color: #0000ff">public</span> Student(String id,String name,<span style="color: #0000ff">int</span><span style="color: #000000"> age){
  6.     </span><span style="color: #0000ff">this</span>.id =<span style="color: #000000"> id;
  7.     </span><span style="color: #0000ff">this</span>.name =<span style="color: #000000"> name;
  8.     </span><span style="color: #0000ff">this</span>.age =<span style="color: #000000"> age;
  9. }
  10. </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">boolean</span><span style="color: #000000"> equals(Object obj){
  11.     </span><span style="color: #0000ff">if</span>(obj == <span style="color: #0000ff">null</span><span style="color: #000000">){
  12.         </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
  13.     }
  14.     </span><span style="color: #0000ff">if</span>(<span style="color: #0000ff">this</span> ==<span style="color: #000000"> obj){
  15.         </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
  16.     }
  17.     </span><span style="color: #0000ff">if</span>(obj.getClass() != <span style="color: #0000ff">this</span><span style="color: #000000">.getClass()){
  18.         </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
  19.     }
  20.     Student student </span>=<span style="color: #000000"> (Student)obj;
  21.     </span><span style="color: #0000ff">if</span>(!<span style="color: #000000">student.getName().equals(getName())){
  22.         </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
  23.     }
  24.     </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
  25. }
  26. </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span><span style="color: #000000"> compareTo(Student student) {
  27.     </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">this</span>.age -<span style="color: #000000"> student.age;
  28. }
  29. </span><span style="color: #008000">/**</span><span style="color: #008000"> 省略getter、setter方法 </span><span style="color: #008000">*/</span><span style="color: #000000">
  30.  
  31. }

Student类实现Comparable接口和实现equals方法,其中compareTo是根据age来比对的,equals是根据name来比对的。

  1. public static void main(String[] args){
  2. List<Student> list = new ArrayList<>();
  3. list.add(new Student("1", "chenssy1", 24));
  4. list.add(new Student("2", "chenssy1", 26));
  5.     Collections.sort(list);   </span><span style="color: #008000">//</span><span style="color: #008000">排序</span>
  6.  
  7. Student student = new Student("2", "chenssy1", 26);

  8.     </span><span style="color: #008000">//</span><span style="color: #008000">检索student在list中的位置</span>
  9.     <span style="color: #0000ff">int</span> index1 =<span style="color: #000000"> list.indexOf(student);
  10.     </span><span style="color: #0000ff">int</span> index2 =<span style="color: #000000"> Collections.binarySearch(list, student);
  11.     System.out.println(</span>&quot;index1 = &quot; +<span style="color: #000000"> index1);
  12.     System.out.println(</span>&quot;index2 = &quot; +<span style="color: #000000"> index2);
  13. }</span></pre>
  14.  

按照常规思路来说应该两者index是一致的,因为他们检索的是同一个对象,但是非常遗憾,其运行结果:

  1. index1 = 0
  2. 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

Java提高篇(三八)-----Java集合细节(四):保持compareTo和equals同步的更多相关文章

  1. java提高篇-----理解java的三大特性之封装

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  2. java提高篇(三)-----java的四舍五入

    Java小事非小事!!!!!!!!!!!! 四舍五入是我们小学的数学问题,这个问题对于我们程序猿来说就类似于1到10的加减乘除那么简单了.在讲解之间我们先看如下一个经典的案例: public stat ...

  3. java提高篇(四)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  4. java提高篇(二)-----理解java的三大特性之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  5. java提高篇(三)-----理解java的三大特性之多态

    面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...

  6. java提高篇(二)-----理解java的三大特性之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  7. (转)java提高篇(二)-----理解java的三大特性之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  8. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  9. java提高篇(二四)-----HashSet

          在前篇博文中(java提高篇(二三)-----HashMap)详细讲解了HashMap的实现过程,对于HashSet而言,它是基于HashMap来实现的,底层采用HashMap来保存元素. ...

  10. java提高篇(十四)-----关键字final

    在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有用武之地了.final是java的关键字,它所表示的是"这部分是无法修改的".不想被改变的原因有两个:效 ...

随机推荐

  1. Test注解的两个属性(转)

    Test注解的两个属性:expected和timeout Junit的Test注解支持两个可选的参数expected和timeout.expected声明一个测试方法必须抛出一个异常.如果不抛出异常或 ...

  2. ember - 观察者模式

    Ember可以察觉所有属性的变化,包括计算属性.观察者是非常有用的,特别是计算属性绑定之后需要同步的时候. 观察者经常被Ember开发过度使用.Ember框架本身已经大量使用观察者,但是对于大多数的开 ...

  3. DOS:将某文件夹下面的所有某一类型文件名输出

    C:\Users\lv>cd /d C:\Siemens\Teamcenter11\lib C:\Siemens\Teamcenter11\lib>dir /B *.lib >lis ...

  4. 向NFV过渡 这三个坑我替你趟了

    网络功能虚拟化(NFV)在最近几年不断发展,并开始现实商业部署.通信服务商也必须解决自身所面临的挑战,包括安全.性能.投入产出比.与现有网络实现电信级交互.运营支撑系统(OSS)和业务支撑系统(BSS ...

  5. android命令抓LOG

    手机和电脑,在电脑上开3个命令窗口,分别输入如下3个命令分别抓取mainLog.radioLog和kernalLog adb logcat -v time >main.txt adb logca ...

  6. JSTL和EL表达式多重if问题

    俾人以前在写一个查询功能时,由于结果状态分好几种,于是页面就用<c:if></c:if>写了一大堆来判断,后来上网查了下资料,发现有个语法类似于多重if,挺方便的,语法是 &l ...

  7. jquery中是否加()的问题

    自己总结的,慢慢修改再: 1带上()代表立即执行 去掉()代表当有事件发生的时候,我再执行

  8. HTML5所有标签汇总

    来自lampbrother兄弟连HTML5与CSS3教程.<xmp> 结构标签:(块状元素) 有意义的div<article>     标记定义一篇文章<header&g ...

  9. 用 R 进行高频金融数据分析简介

    作者:李洪成 摘自:http://cos.name/wp-content/uploads/2013/11/ChinaR2013SH_Nov03_04_LiHongcheng.pdf 高频数据 金融市场 ...

  10. VS2010 网页错误

    VS2010向导添加消息处理时,弹出以上错误,原因之一为: 类内没有定义IDD的宏