如何使用equals()和hashCode()实现近似几何等式

kos*_*tja 2 java hash geometry equality hashcode

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

为此,在系统范围delta内使用几何相等性。equals()for点通过使用deltafor近似相等的距离计算来实现。

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

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

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

什么是合理的解决方案?我在滥用目的hashCode()吗?哪一个仍然是最合理的解决方案hashCode():)

编辑:谢谢,我有一个直觉,这个想法出了点问题,但我不能对此表示怀疑。你说得很清楚

请允许我将问题扩展到:如果我对较慢的HashSet操作没问题(这不是最有效的方法),那么由于没有正确的实现,我可能会hashCode()返回1,这将带来可怕的后果(它涉及几何计算) ),如果我确实实施了equals()降低传递性要求?

编辑我找到了这篇文章,着重介绍了缺少传递性的问题,并且这篇文章这篇文章密切相关。

SLa*_*aks 5

从根本上讲这是不可能的。

equals()/ hashCode()基于平等只能在数学定义的等价关系服从三个规则:

  • 一个〜一个 (反射性)
  • 如果a〜b,则b〜a。(对称)
  • 如果a〜b和b〜c则a〜c。(传递性)

您的定义不是可传递的,因此您无法使用它。
相反,您需要备用数据结构。


Sea*_*wen 5

hashCode()对于非equals()对象可以相等。因此,确实可以进行存储。例如,如果仅使用最接近的“网格”点的某个哈希函数,可以在其中随意定义该网格,只要您一致且正确地定义舍入,它就可以作为哈希函数。

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

您可以equals()根据存储区进行定义。当点接近但线的另一侧不相等时,可能会给出令人惊讶的结果。