- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
来自 TreeMap 的 JavaDoc:
Note that the ordering maintained by a sorted map (whether or not an explicit comparator is provided) must be consistent with equals if this sorted map is to correctly implement the Map interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.
有人可以举一个具体的例子来说明如果排序与 equals 不一致时可能出现的问题吗?以具有自然顺序的用户定义类为例,即它实现了 Comparable 。 JDK 中的所有内部类是否都维护此不变性?
最佳答案
这是一个简单但实际的例子,说明如果比较方法与 equals 不一致会发生什么。在JDK中,BigDecimal
实现了Comparable
,但其比较方式与equals不一致。例如:
> BigDecimal z = new BigDecimal("0.0")
> BigDecimal zz = new BigDecimal("0.00")
> z.compareTo(zz)
0
> z.equals(zz)
false
这是因为BigDecimal
的比较方法只考虑了数值,而equals
还考虑了精度。由于 0.0
和 0.00
具有不同的精度,因此即使它们具有相同的数值,它们也不相等。 (有关解释,请参阅 this answer .)
下面是一个示例,说明 TreeSet
违反 Set
的一般契约意味着什么。 (这与 TreeMap
和 Map
的情况相同,但使用集合更容易演示。)让我们将 contains
的结果与结果进行比较从集合中取出元素并调用 equals
:
> TreeSet<BigDecimal> ts = new TreeSet<>()
> ts.add(z)
> ts.contains(z)
true
> z.equals(ts.iterator().next())
true
> ts.contains(zz)
true
> zz.equals(ts.iterator().next())
false
这里令人惊讶的是 TreeSet
说它包含对象 zz
,但它不等于集合中实际包含的元素。原因是 TreeSet
使用它的比较方法 (BigDecimal.compareTo
) 来确定集合成员资格,而不是 equals
。
现在让我们比较一下 TreeSet
和 HashSet
:
> HashSet<BigDecimal> hs = new HashSet<>(ts)
> hs.equals(ts)
true
> ts.contains(zz)
true
> hs.contains(zz)
false
这很奇怪。我们有两个相等的集合,但是一个集合说它包含一个对象,而另一个集合说它不包含同一个对象。同样,这反射(reflect)了 TreeSet
使用的是比较方法,而 HashSet
使用的是 equals
。
现在让我们将另一个对象添加到 HashSet
中,看看会发生什么:
> HashSet<BigDecimal> hs2 = new HashSet<>()
> hs2.add(zz)
> ts.equals(hs2)
true
> hs2.equals(ts)
false
这很奇怪。一组说它等于另一组,但另一组说它不等于第一组!要理解这一点,您需要了解如何确定集合的相等性。如果 a) 它们具有相同的大小,并且 b) 另一个集合中的每个元素也包含在这个集合中,则两个集合被认为是相等的。也就是说,如果你有
set1.equals(set2)
然后相等算法查看大小,然后遍历 set2,并针对每个元素检查该元素是否包含在 set1 中。这就是不对称的来源。当我们这样做时
ts.equals(hs2)
两个集合的大小都是 1,所以我们继续迭代步骤。我们迭代 hs2
并使用然后调用 TreeSet.contains
方法——它使用比较方法。就TreeSet
而言,它等于HashSet
hs2。
当我们这样做的时候
hs2.equals(ts)
比较是相反的。我们遍历 TreeSet
并获取它的元素,然后询问 hs2
它是否 包含
该元素。由于HashSet.contains
使用了equals,所以返回false,整体结果为false。
关于java - compare consistent with equals 是什么意思?如果我的类(class)不遵循这个原则,可能会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12123960/
GitOps描述了一种使用植根于 Git 版本控制系统的方法来操作和管理软件的方法。使用基于 GitOps 的工作流,通过要求将系统的特征定义为 Git 存储库中的文件,可以更轻松地开发、部署、维护和
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 6 年前。
命令行货币转换器应用程序,提示用户输入源货币、源货币代码和目标货币代码,例如 C:\workspace> java CurrencyConverter 100.50 EUR GBP 应用程序返回源金额
得到这个实体: /** * @ORM\Table(name="shop_payment_details") * @ORM\Entity(repositoryClass="Acme\ShopBund
我有一个原则实体,无需调用 persist 或 flush 即可持久保存到数据库中。 我在下面很简单地重现了这个问题。正如您将看到的,此脚本从名为 MyEntity 的数据库表中加载一行,并获取一个以
在我的编程实践中,我经常遇到客户端和服务器端脚本之间数据重复的问题。 在这种情况下,我们可以讨论客户端的 JavaScript 和服务器端的 PHP 或 C# (ASP.NET)。 比方说,我有一段
简介 我在写关于继承问题的硕士论文并解决了一些问题 表明存在继承问题的指标。 像下面的例子: 示例 public static String getAnimalNoise(Animal animal)
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
当我注意到this answer时,我一直在阅读里氏替换原理。 。它有一个 Circle 和一个 ColoredCircle 类型,其中 ColoredCircle 的构造函数需要一个额外的参数; 颜
这段代码是否违反了DRY原则? if (notAuthorized) { return sendErrorCode(new ForbiddenException()) } else if (n
我在查询中使用 Doctrine 2 的结果缓存来检索用户(消息传递应用程序)的新消息数量: $query->useResultCache(true, 500, 'messaging.nb_new_m
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
如何设置包含类名的变量,例如 android.util.Log 中的 TAG,同时尊重 Dont-Repeat-Yourself? 以下是一些可能性: 在 Google 代码中,它的常用用法如下 pu
我有以下查询: $roles = array(); $roles[] = 'ROLE_SUPER_ADMIN'; $roles[] = 'ROLE_ADMIN';
下面的代码违反了哪一条 SOLID 原则? public class A { void hello(){ //some code here } } public class B ext
我目前有一个 Message_Repository 类,它有如下方法: getLocationDetailsByID($messageId), getCustomerDetailsById($mess
我不知道它到底叫什么,但现在我将它称为“非空测试”。在 C# 8 中有一个新的行为允许测试一个对象是否不为空,例如: Foo foo = new Foo(); if(foo is { }) {
我正在学习 Doctrine。我在多对多关系中有两个实体 Article 和 Category,我正在尝试获取所有不是特定文章的类别。 文章实体: class Article extends Base
在阅读了一本书和一篇在线文章中有关 SOLID 代码的内容后,我想重构一个现有的类,使其与“SOLID”兼容。 但我想我迷路了,尤其是依赖注入(inject):当我想实例化类的一个对象时,我需要“注入
我的项目中有类似的东西,这个项目已经完成了(它正在运行)我只想知道 SOLID 原则是否可以接受 static public class Tools { static public GetPr
我是一名优秀的程序员,十分优秀!