Java周二生效! 考虑实现“可比较”

今天,我们进入本节的最后一章,介绍所有对象通用的方法。 与本节中讨论的其他方法不同,该方法实际上不是类上的方法宾语。 话虽如此,该方法确实会影响其他各种类中的默认操作,因此理解这一点很重要。 我们今天谈论的方法是相比于和它的相关界面可比。

那么,什么是目的可比接口? 其目的与宾语的等于但是,其目的是进行顺序比较和相等性比较。 当您实施时可比您表示实例的顺序自然,并提供了一种以这种方式组织实例的方法。 一旦实现了接口,对它们的数组进行排序就很简单Arrays。sort(myArray)。

假定可以确定自然顺序,这使得保留排序的集合,搜索值或查找最大值和最小值变得很简单。 例如填写树集(使用相比于对其内部数据结构进行排序的方法)串对象(实现可比),最后得到按字母顺序排列的值列表。 的可比接口提供了很多价值,这很可能是为什么几乎所有Java内置值类型都实现此接口的原因。 如果您正在编写的值类具有自然顺序,那么也可以实现此接口。

我们来看一下界面和合同。 的可比界面如下所示:

public interface Comparable<T> {
  int compareTo(T t);
}

这使得界面相当简单。 一种接受通用类型并返回整数的方法。 因此,让我们来看一下合同相比于方法:

  • 的相比于当对象小于,等于或大于提供的对象时,方法应返回负数,零或正数。扔一个ClassCastException如果提供的对象类型不兼容,则无法与该对象进行比较。

接下来的几项利用了信号数学函数,表示为标志()下面。 简而言之,此方法为负数返回-1,为0返回0,为正数返回1。

  • 对全部X和ÿ,sgn(X.相比于(ÿ)) == -sgn(ÿ.相比于(X))Related to the above,X.相比于(ÿ) should onlÿ throw an eXception if ÿ.相比于(X) also throws an eXception.与相同等于 function,相比于 should be transitive. Therefore,if X.相比于(ÿ) > 0 && ÿ.相比于(z) > 0然后X.相比于(z) > 0。 这也应该与<和==

之间的比较相比于和等于 has been brought up before in this post和相比于确实返回0当物品是等于那应该是什么时候等于退货真正应该相比于总是回来0? The question comes down to, does object 等于ity equate to natural ordering? Often it is the case that these are one in the same和can be surprising when they aren't the same.

让我们来看一个令人惊讶的例子。 的大十进制类以与众不同的方式实现可比性等于实施。 所以给一个哈希集(这利用了等于方法)有两个项目new 大十进制("1.0")和new 大十进制("1.00")。 的哈希集最后会有两个条目。 比较一下,将这两个相同的项目放入一个树集(使用相比于 method)和we would end up with only one item in the collection. Doesn't quite pass the principle of last surprise does it? Thus, even though it's not required, it is strongly suggested that when two objects return 真正至等于那些相同的两个对象最终返回0从相比于。 至少,如果不遵循此建议,则应充分证明它没有遵循此预期。

那么,如何写一篇相比于方法。 与编写等于方法。

  1. 确定类的字段的重要性顺序。通过递归调用比较字段相比于引用类型的方法或使用内置方法之一BoxedTime.compare()诸如Double.compare()。一旦找到不相等的字段,则返回该字段的值(或者如果没有差异,则返回0)。

让我们看一个例子:

public int compareTo(PhoneNumber pn) {
  int result = Short.compare(areaCode, pn.areaCode);
  if (result != 0) {
    result = Short.compare(prefix, pn.prefix);
    if (result == 0) {
      result = Short.compare(lineNumber, pn.lineNumber);
    }
  }
  return result;
}

不是超级复杂,但是您可以看到它如何变得很深。 Java 8提供了一种替代方案,可以使最终结果更加简洁。

private static final Comparator<PhoneNumber> COMPARATOR = 
  comparingInt((PhoneNumber pn) -> pn.areaCode)
    .thenComparingInt(pn -> pn.prefix)
    .thenComparingInt(pn -> pn.lineNum);

public int compareTo(PhoneNumber pn) {
  return COMPARATOR.compare(this, pn);
}

如您所见,这将更加简单和简洁。 无论我们正在比较多少项,它都不会更深入。 权衡是一点点性能。

您偶尔会看到的一些东西在当时似乎是个好主意,这是利用了两个值之间的差为负的事实。 因此,从另一个减去一个可能导致履行合同。 麻烦的是您可以处理整数溢出和其他此类问题。 最好使用比较方法来降低性能。

不幸的是,用这种方法我不知道像龙目岛可以产生相比于我们的方法。 在这种情况下,我们确实需要自己处理此方法的创建。 总结本章,当您创建具有自然顺序的值类型时,应考虑实施可比接口。 这样就可以轻松地对您的值类型进行排序,搜索并在基于比较的集合中使用。

from: https://dev.to//kylec32/effective-java-tuesday-consider-implementing-comparable-3m9j

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值