2

我正在尝试使用 hazelcast 多映射和已序列化数据的映射,即键和值都是字节数组。如下所示,它没有按预期工作。

在 javadoc 中,在“gotchas”部分中指出,散列是由 hazelcast 在序列化形式上处理的,不依赖于 hashCode 和 equals 的实现(在字节数组的情况下不会被覆盖)。所以,我不明白为什么显然使用了 Object.hashcode 。

有人可以告诉我如何使用带有字节数组的榛树地图吗?

我是否有义务使用充分覆盖的哈希码/相等方法存储字节数组包装器?

谢谢你的帮助。

问题:

 scala> val mm:MultiMap[Array[Byte], Array[Byte]] = hi.getMultiMap("test-baMuMa")
 mm: com.hazelcast.core.MultiMap[Array[Byte],Array[Byte]] = MultiMap [test-baMuMa]

 scala> mm.put("a".getBytes,"b".getBytes)
 res29: Boolean = true

 scala> mm.put("a".getBytes,"b".getBytes)
 res30: Boolean = true
 // => should return false..

 scala> mm.remove("a".getBytes,"b".getBytes)
 res31: Boolean = false
 // =>  should return true

 scala> mm.containsEntry("a".getBytes,"b".getBytes)
 res32: Boolean = false
 // =>  should return true (confirmed that removal did not occur)
4

1 回答 1

1

我在这里回答我自己的问题,因为我认为在 hazelcast 文档中并没有像它可能的那样清楚地说明:

  • 关键对象不需要覆盖equals/hashcode
  • 值对象需要覆盖equals/hashcode

通过这个简单的测试可以看出这一点:

object TestHazel{

  class Klaus(a:Int) extends Serializable
  // class does not override equals/hashcode

  def main (args:Array[Byte]){
    import com.hazelcast.core._
    val hi = Hazelcast.newHazelcastInstance
    val map = hi.getMap[Klaus, Klaus]("asdf")
    val klaus1 = new Klaus(1)
    map.put(klaus1, klaus1)
    val containsKey = map.containsKey(new Klaus(1))
    println("\n\ncheck if key overrides equals/hashcode: " + containsKey)
    // true

    val containsValue = map.containsValue(new Klaus(1))
    println("\n\ncheck if value overrides equals/hashcode: " + containsValue + "\n\n")
    // false

    hi.shutdown
 }
}

因此,就我而言,对于字节数组值,需要一个覆盖等于和哈希码的包装器。不幸的是,值类 scala >= 2.10 不能与覆盖 equals/hashcode 的类一起使用,所以我们无法避免装箱:-(

此外,如果您想按顺序索引,则包装器必须是可比较的。

这是这种包装器的合理实现:

class BAWrapper2(ba:Array[Byte], comparator:Comparator[Array[Byte]]) 
    extends Serializable with Comparable[BAWrapper2] 
{
  def data: Array[Byte] = if (ba == null) Array.empty[Byte] else ba
  def equals(other:BAWrapper2):Boolean = util.Arrays.equals(data, other.data)
  override def equals(obj:Any):Boolean = 
    if (obj.isInstanceOf[BAWrapper2]) equals(obj.asInstanceOf[BAWrapper2]) 
    else false
  override def compareTo(that:BAWrapper2):Int =
    if (comparator != null) comparator.compare(this.data, that.data)
    else BAComparator.compare(this.data, that.data)
  override def hashCode:Int = util.Arrays.hashCode(data)
}
于 2013-03-06T11:01:13.743 回答