UDN-企业互联网技术人气社区

板块导航

浏览  : 969
回复  : 0

[讨论交流] 5 分钟搞定 Java Comparable 接口

[复制链接]
哥屋恩的头像 楼主
发表于 2016-10-29 19:07:57 | 显示全部楼层 |阅读模式
  这篇文章是免费Java 8 课程中关于Clean Code原则的一部分。

  在这篇文章中,我们要聊一聊Java Comparable接口。

  还有一个不错的视频可以点这里

  Comparable接口时用来干什么的呢?

  我们应该如何对事物进行比较和排序?这问题听上去有点莫名其妙,但我希望你认真考虑一下。比方说,我们有一组苹果:

3.png

  例1

  我们要怎样对它们进行排序呢?我们希望通过重量进行排序吗?如果是的话,排序是从最轻到最重还是从最重到最轻?当我们对它们进行排序的时候,我们需要反复比较两个苹果的重量,直到正确地排好所有的苹果。苹果1比苹果2重?那它比苹果3重吗?我们需要不断比较,直到完成排序。Comparable接口可以帮助我们实现这一目标。Comparable本身不能对对象进行排序,但接口定义的方法 int compareTo(T)可以。

  compareTo(T)如何工作

  让我们通过使用compareTo()方法来看看哪个苹果更重,开始吧。

2.png

  例2

  compareTo()方法的工作原理是返回一个int值——或正,或负,或为零。它通过调用作为参数的对象来比较对象。负数表示调用的对象比参数“轻”。如果我们用大小来比较苹果,那么上面的调用会返回一个负数,例如-400,因为红苹果比青苹果小。如果两个苹果重量相等,那么调用将返回0。如果红苹果更重,那么compareTo()将返回一个正数,例如68。

  compareTo()的灵活性

  如果我们反复调用上面的compareTo()方法,那么我们可以通过大小来排序,这很棒,但并非故事的结束。如果我们想通过颜色来给苹果排序呢?抑或是重量?我们也可以做到。关键是,我们的客户——让我们叫他胖子农夫(见例3),需要在我们开始开发之前精确定义需要如何对苹果进行排序。

1.png

  例3

  他可以通过回答这两个问题来做到这一点:

  他希望苹果如何进行排序?他希望我们比较什么特征?

  在那样的环境中,“小于”,“等于”和“大于”指的是什么意思?

  也可以使用多个特征,这个后面我们会讲。

  例1:通过重量排序苹果

  在第一个例子中,我们将通过重量对苹果排序。只需要一行代码。

  Collections.sort(apples);

  例4

  上面的代码行可以为我们做到所有的排序工作,只要我们事先定义好如何对苹果进行排序(这就需要多行代码了)。

  让我们开始写苹果类吧。

  1.   public class Apple implements Comparable {

  2.   private String variety;

  3.   private Color color;

  4.   private int weight;

  5.   @Override

  6.   public int compareTo(Apple other) {

  7.   if (this.weight < other.weight) {

  8.   return -1;

  9.   }

  10.   if (this.weight == other.weight) {

  11.   return 0;

  12.   }

  13.   return 1;

  14.   }

  15.   }
复制代码


  例5

  这是Apple类的第一个版本。由于我们使用的是compareTo方法,并且正在排序苹果,所以我实现了Comparable接口。在这第一个版本中,我们通过重量比较对象。在我们的compareTo()方法中,我们写一个if条件,说明如果这个苹果的重量小于其他的苹果,那么返回一个负数,为了保持简单,我们假定它为-1。请记住,这意味着这个苹果轻于Apple ‘other’。在第二个if语句中,我们要说明,如果苹果重量相等,那么返回一个0。当然,如果这个苹果既不是更轻,又不是一样重,那就只能比其他苹果更重了。在这种情况下,我们返回一个正数,假定为1。

  例2:通过多个特征排序苹果

  正如我前面提到的,我们还可以使用compareTo()比较多个特征。比方说,我们第一通过品种排序苹果,但如果两个苹果是同一品种,那么我们就按颜色排序。最后,如果这两个特性相同,那么我们将按重量排序。虽然我们可以手动实现这件事,就像我在最后一个例子中做的那样,但是其实可以用一种简洁得多的方式实现。一般来说,最好是重用现有的代码,而不是自己写。我们可以在Integer、String和枚举类中使用compareTo方法来比较值。由于我们没有使用Integer对象,用了int,所以我们不得不使用来自于Integer包装器类的一个静态的helper方法来比较两个值。

  1.   public class Apple implements Comparable {

  2.   private String variety;

  3.   private Color color;

  4.   private int weight;

  5.   @Override

  6.   public int compareTo(Apple other) {

  7.   int result = this.variety.compareTo(other.variety);

  8.   if (result != 0) {

  9.   return result;

  10.   }

  11.   if (result == 0) {

  12.   result = this.color.compareTo(other.color);

  13.   }

  14.   if (result != 0) {

  15.   return result;

  16.   }

  17.   if (result == 0) {

  18.   result = Integer.compare(this.weight, other.weight);

  19.   }

  20.   return result;

  21.   }

  22.   }
复制代码


  例6

  在例6中,我们比较了客户指定的苹果的第一特性,它们的品种。如果compareTo()调用的结果为非零,那么我们返回值。否则,我们调用另一个compareTo()直到得到一个非零值,或者直到已经比较完这三个特征。尽管此代码可以工作,但它不是最有效或干净的解决方案。在例3中,我们重构我们的代码,使其更简单。

  1.   @Override

  2.   public int compareTo(Apple other) {

  3.   int result = this.variety.compareTo(other.variety);

  4.   if (result == 0) {

  5.   result = this.color.compareTo(other.color);

  6.   }

  7.   if (result == 0) {

  8.   result = Integer.compare(this.weight, other.weight);

  9.   }

  10.   return result;

  11.   }
复制代码


  例7

  正如你所看到的,这大大减少了代码,并且每一次比较只要一行代码。如果一个compareTo()调用的结果是零,那么我们就转移到下一个相同if语句的比较中。顺便说一句,这是成为Clean Coder的一个很好的例子。通常情况下,你不需要立即写出干净的代码;你可以从一个粗略的想法开始,使其可以工作,然后不断改进,直到你尽可能得让它干净就可以了。

  Comparable,hashCode以及Equals

  你可能会注意到compareTo()看起来有点像hashCode()和equals()方法。但是,它们有一个重要的区别。对于hashCode()和equals()方法,比较个体属性的顺序不影响返回的值,但是,在compareTo()中,通过你比较对象的顺序来定义对象的顺序。

  结论

  在结论中我只想强调Comparable接口是多么的重要。它既用于java.util.Arrays,也用于java.util.Collections实用程序类,来排序元素和搜索排序集合中的元素。使用TreeSet和Tree Map,就更简单了——想要它们会自动排序必须实现Comparable接口的元素。

原文作者:佚名  来源:开发者头条

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部