【问题标题】:What is the clojure equivalent of Overriding "equals" in java?java中覆盖“等于”的clojure等价物是什么?
【发布时间】:2011-10-06 15:39:32
【问题描述】:

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

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

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

在 java 中,我发现这个工具在制作以数千个 bean 作为键的高速地图时非常强大。

【问题讨论】:

    标签: java clojure hashtable


    【解决方案1】:

    为了希望让这个讨论更加清晰,在 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”数据结构解决方案,而不是走 hashcode、equals、Java 互操作之路。

    【讨论】:

    • “纯 Clojure”数据结构解决方案是什么样的?
    【解决方案2】:

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

    违背 equals 的预期行为很可能会以某种方式在某个地方造成麻烦。而且,当您真正需要它们时使用您自己的类似集合的复合材料并不会太难,而不会将您的意志强加于 core equals 上。

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 只要你覆盖你的哈希函数,覆盖equals就可以了。一点也不疯狂——标准的、共同的好设计。如果您覆盖另一个,任何好的 GUI/lint 类型程序都会提醒您覆盖另一个。使用比较器是一种更糟糕的模式,因为它将知识从你的类导出到另一个(比较器)
      • 这看起来有点范式冲突。有些人在想“自包含的对象,问它们是否相等”,而另一些人在想“不可变值的组合”,其中相等的概念是普遍的。
      • 我不反对覆盖 equals - 这显然在 Java 中经常是必要的。 以他要求的方式覆盖它是一个糟糕的主意,因为不可能编写一个hashCode 函数来符合让equals 为至少共享的任何地图返回true 的决定这个有两把钥匙。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-15
      • 2014-03-11
      • 2012-07-03
      • 1970-01-01
      • 2021-10-18
      • 2010-12-07
      • 2013-03-12
      相关资源
      最近更新 更多