【问题标题】:Not able to retrieve element from Hazelcast's Map if using custom object as a key如果使用自定义对象作为键,则无法从 Hazelcast 的地图中检索元素
【发布时间】:2016-12-20 09:05:39
【问题描述】:

我正在使用 Hazelast Map 并尝试根据我的自定义类的对象(即 HMapKey)存储对象。这是HMapKey类的sn-p。

public class HMapKey implements Serializable{
    private String keyCode;
    private long time;

    public HMapKey(String keyCode, long time) {
      this.keyCode = keyCode;
      this.time = time;
    }
    public String getKeyCode() {
        return keyCode;
    }
    public void setKeyCode(String keyCode) {
        this.keyCode = keyCode;
    }
    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((keyCode == null) ? 0 : keyCode.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        HMapKey other = (HMapKey) obj;
        if (keyCode == null) {
            if (other.keyCode != null)
                return false;
        } else if (!keyCode.equals(other.keyCode))
            return false;
        return true;
    }
}

正如您在上面的代码中看到的,我只在 equals() 方法中使用了keyCode 来比较两个对象。所以无论time 变量有什么值。 但是当我在 Hazelcast 的 Map 中使用这个对象作为键并尝试检索它时,我认为 Hazelcast 检查键类的每个变量,因此,即使我有相同的keyCode 变量值和不同的time 变量,Hazelcast 将我返回为NULL。是否有任何配置告诉 Hazelcast 不要进行所有变量检查并仅使用现有的 equals() 方法?

这是我尝试从地图中检索数据的代码

HazelcastInstance instance = Hazelcast.newHazelcastInstance();
private static ConcurrentMap<HMapKey, String>   testMap = instance.getMap("TEST_MAP");
testMap.put(new HMapKey("code1",123), "This is Code 1");
System.out.println(testMap.get(new HMapKey("code1",0)));

意味着,在插入时,我创建了像 new HMapKey("code1",123) 这样的键对象,但在检索它时,我正在创建新对象为 new HMapKey("code1",0),这将我返回为空值。而如果我尝试使用new HMapKey("code1",123),它工作正常。

【问题讨论】:

  • 你能把代码贴在你试图从地图中检索的地方吗?
  • 更新了我的问题。

标签: hazelcast hazelcast-imap


【解决方案1】:

首先,当你说“我试图找回它”时,我不知道你在试图做什么。

如果您在 get 方法中使用密钥,一切正常:

@Test
public void test() {
    HazelcastInstance hz = createHazelcastInstance();

    IMap<HMapKey, Integer> map = hz.getMap("aaa");
    HMapKey key = new HMapKey();
    key.keyCode = "code1";
    key.time = 123;

    HMapKey key2 = new HMapKey();
    key2.keyCode = "code2";
    key2.time = 246;

    map.put(key, 1);
    map.put(key2, 2);

    int value = map.get(key);
    assertEquals(value, 1);
}

如果要根据整个键值检索值,则 HMapKey 需要实现 Comparable

然后你可以这样查询:

map.values(Predicates.equal("__key", yourHKMapKeyInstance));

【讨论】:

  • @tom,即使你实现Comparable它也不起作用
【解决方案2】:

您可以通过将变量time 声明为transient 来实现。但请注意,它会导致碰撞并给出随机结果。即使它的属性不同,您的 put 操作也会覆盖以前的值。

HazelcastInstance instance = Hazelcast.newHazelcastInstance();
IMap<HMapKey, String> testMap = instance.getMap("TEST_MAP");

testMap.put(new HMapKey("code1",123), "This is Code 1");

System.out.println("HMapKey with time=0: " + testMap.get(new HMapKey("code1",0)));
System.out.println("HMapKey with time=123: " + testMap.get(new HMapKey("code1",123)));


testMap.put(new HMapKey("code1",456), "This is Code 2");
System.out.println("HMapKey with time=123: " + testMap.get(new HMapKey("code1",123)));

输出将是:

HMapKey with time=0: This is Code 1
HMapKey with time=123: This is Code 1
HMapKey with time=123: This is Code 2

【讨论】:

  • 谢谢.. 它对我有用。但这是唯一的方法吗?因为我想在集群上使用那个 time 变量。但这不应该是验证密钥的一部分。
  • 我相信是的。您也许可以探索序列化主题以检查它如何转换密钥。如果您想使用 time 变量,最好将其包含在您的 hashcode/equals 实现中。
【解决方案3】:

Hazelcast 不反序列化键/值并执行equalshashCode 方法,但通过其对应的字节流比较序列化对象。如果您正在搜索一处或多处房产,请查看 Tom https://stackoverflow.com/a/41238649/917336 的回答

【讨论】:

  • 如果我想使用类中的单个元素来验证关键对象,而不是像你提到的字节流,有什么办法吗?我尝试了汤姆的回答,但没能实现。
  • 您无法验证,只能查询并查看结果是否符合您的预期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-28
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多