在java中覆盖“等于”的clojure相当于什么?

时间:2011-10-06 15:39:33

标签: java clojure hashtable

我最近在clojure中询问了地图中的复合键:How can you implement Composite keys in clojure? ...

答案是它们的工作方式类似于java键 - 如果某些内容覆盖“等于”,那么它可以有效地用作键。

我想知道:是否有宏允许我们覆盖自定义数据结构的“等于”?例如,假设我想使用Map作为键,并将唯一性定义为“如果此映射包含与另一个映射共同的2个或更多元素,则它们是相等的”。我怎样才能覆盖地图的默认行为?

在java中,我发现在制作包含数千个bean作为键的高速地图时,这个功能非常强大。

3 个答案:

答案 0 :(得分:5)

希望在本次讨论中增加一点清晰度,在Java中,通常会覆盖hashCodeequals。例如,您正在尝试跟踪具有名称但可能还有昵称的员工。目标是确保这些员工不会重复。在这种情况下,我会覆盖equalshashCode,只查看员工的ID。当这些员工进入Set数据结构时,它们不会重复。在Clojure中,您可以这样做:

(deftype Employee [name id]
  Object
  (equals [a b] (= (.id a) (.id b)))
  (hashCode [this] (.hashCode (.id this)))
  (toString [this] (.name this)))

(def vince (Employee. "Vince" 42))

(def vincent (Employee. "Vincent" 42))

(def tony (Employee. "Tony" 2))

(into #{} [vince vincent tony])

但您可能希望采用“纯Clojure”数据结构解决方案,而不是使用哈希码,等于Java互操作路径。

答案 1 :(得分:4)

并不是clojure集合覆盖等于;在你做一些有趣的事情的几乎每个地方都会发生压倒一切的平等。 Clojure类型提供了equals的实现,这些实现旨在与整个语言保持一致(可以说是打算使用Java等于的方式)。这意味着“相等”的东西应该是集合中的单个项目,而地图中的单个键,总是无处不在。语言设计取决于此。 Clojure 1.3做了一些明确的非向后兼容的更改,以更接近理想。

与某种平等的预期行为相反,很可能会在某处造成麻烦。当你真正需要它们时,使用你自己的类似组合的复合材料并不是很难,而不会强迫你的核心等于你的意志。

也就是说,如果你真的想要,可以使用许多java互操作函数和宏来变换equals系统。请参阅http://clojure.org/datatypes作为起点。

答案 2 :(得分:1)

这在Clojure和Java中都很疯狂。 不要这样做。你将破坏Object类和Map接口的契约;如果他们使用你的自定义地图类,那么各种事情都会完全崩溃。如果你声明两个对象是equal,那么它们的哈希码必须是相同的,否则持有它们的HashMap将无法应对。当然,你可以将所有哈希值设为0,但是你的高性能地图 - 它现在是一个链表。

也就是说,你可以在Clojure或Java中通过使用自定义Comparator sorted-map(或分别为SortedMap)来做类似的事情。但是,如果您选择的比较器实际上实现了相等性,而是某种“模糊相等”,则会有数以万计的陷阱。