在groovy中动态覆盖`equals`和`hashCode`

前端之家收集整理的这篇文章主要介绍了在groovy中动态覆盖`equals`和`hashCode`前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如果我动态地重写类的equals和hashCode方法,则调用这些方法会直接调用重写版本,但将它们用于set会使用非重写版本.为什么会这样,是否仍然可以为所有用法动态覆盖这两种方法

class SuperClass {
  public boolean equals(Object other) {
    println 'non overridden equals called'
    false
  }

  public int hashCode() {
    println 'non overridden hashCode called'
    1
  }
}

SuperClass.MetaClass.equals = { Object other ->
  println 'overridden equals called'
  true
}

SuperClass.MetaClass.hashCode = { ->
  println 'overridden hashCode called'
  1
}

def a = new SuperClass()
def b = new SuperClass()

println a.hashCode() // overriden hashCode called
println b.hashCode() // overriden hashCode called
println a.equals(b) // overriden equals called

println([a,b].toSet().size()) // non overriden methods called,returns 2 instead of 1

解决方法

在列表 invokes the following code调用toSet():

Set<T> answer = new HashSet<T>(self.size());
    answer.addAll(self);
    return answer;

现在HashSet(一个Java类)没有MetaClass的概念,所以没有看到你重载的hashCode和equals方法.因此,您的套装中有2件物品.

您可以做的是首先在列表中调用unique:

println( [a,b].unique().toSet().size() )

因为这通过调用者所以知道MetaClass并且应该给你一个包含一个元素的集合.

实际上,我会避免通过MetaClass更改hashCode方法.正如您所看到的,很难确切知道何时处理它,以及处理得好的事情可能并不期望hashCode会随时改变.

猜你在找的Groovy相关文章