【问题标题】:How to implement approximate geometric equality using equals() and hashCode()如何使用 equals() 和 hashCode() 实现近似几何相等
【发布时间】:2011-12-23 03:17:07
【问题描述】:

我想实现一些具有数值鲁棒性的几何算法。

为此,系统范围的delta 用于几何相等。用于点的equals() 是通过使用delta 进行距离计算来实现近似相等的。

我希望能够使用常规的 Java 集合,例如 Set。但是我想不出一个合理的hashCode() 实现。

我的猜测是,高效使用HashSet 的实现会导致空间分区带有“软”边界。与分区边界距离小于delta 的点应该能够同时分类到最多八个(对于 3D)相邻区域中。距离足够近而被认为相等但位于分区不同侧的点将被“错误分类”。

这是我无法理解的。 hashCode() 就像将项目放在桶中,单个项目最终放在一个桶中,而我最多需要将其放入八个。

什么是合理的解决方案?我是否在滥用hashCode() 的目的?仍然使用hashCode() 的最合理的解决方案是什么:)

编辑:谢谢,我有一种直觉,认为这个想法有问题,但无法确定。你把事情说得很清楚了

请让我将我的问题扩展到:如果我对较慢的HashSet 操作(这不是一个炫耀)没问题,我可以让hashCode() 返回1,因为在我的情况下没有正确的实现,如果我实现equals() 放弃传递性要求,会有什么可怕的后果(它是几何计算)?

编辑我找到了this post,突出了缺少传递性的问题,以及与此密切相关的this post

【问题讨论】:

    标签: java hash geometry hashcode equality


    【解决方案1】:

    hashCode() 可以等于 un-equals() 对象。所以,事实上,分桶可能就很好了。例如,如果您只使用最近的“网格”点的某个散列函数,您可以在其中任意定义该网格,只要您一致且正确地定义舍入,它将作为散列函数工作。

    但是,您不会从第一个定义中得到正确的 equals() 概念。如果 A 和 B 以及 B 和 C 在彼此的 delta 范围内,这并不意味着 A 和 C 是。传递性不成立。

    您可以根据分桶定义equals()。当点接近但线的另一侧不相等时,它可能会产生稍微令人惊讶的结果。

    【讨论】:

      【解决方案2】:

      这基本上是不可能的。

      equals() / hashCode() 基于数学的相等性只能定义在遵守三个规则的数学 equivalence relations 上:

      • 一个~一个。 (反身性)
      • 如果 a ~ b 然后 b ~ a。 (对称)
      • 如果 a ~ b 和 b ~ c 然后 a ~ c。 (传递性)

      您的定义不具有传递性,因此您不能使用它。
      相反,您需要一个备用数据结构。

      【讨论】:

        【解决方案3】:

        我建议不要使用整个方法。一方面,它会破坏equals 的传递性。 (如果 delta == 0.1,那么 1 == 1.1 和 1.1 == 1.2,但 1 != 1.2。)没有哈希码实现可以解决这个问题。总体而言,它也可能会弄乱集合框架。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-02
          • 1970-01-01
          • 1970-01-01
          • 2010-12-10
          • 2020-02-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多