Not able to retrieve element from Hazelcast's Map if using custom object as a key

2.7k views Asked by At

I am using Hazelast Map and trying to store Objects against key which is object of my custom class i.e. HMapKey. Here is snippet of HMapKey class.

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;
    }
}

As you can see in above code, I have used only keyCode in equals() method to compare two objects. So no matter what value is there for time variable. But when I use this object as key in Hazelcast's Map, and try to retrieve it, I think Hazelcast checking each and every variable of key class, because of this, even if I have same keyCode variable value and different time variable, Hazelcast returning me as NULL. Is there any configuration to tell Hazelcast not to go for all variable checking and use existing equals() method only?

Here is code how I am trying to retrieve data from map

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)));

Means, while insertion, I have created key object like new HMapKey("code1",123) but while retrieving it, I am creating new object as new HMapKey("code1",0) and this is returning me as null value. Whereas if I try with new HMapKey("code1",123) it's working fine.

3

There are 3 answers

2
A.K.Desai On BEST ANSWER

You can achieve that by declaring variable time as transient. But note that it will lead to collisions and give random results. Your put operation would overwrite the previous value even though it's properties are different.

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)));

Output would be:

HMapKey with time=0: This is Code 1
HMapKey with time=123: This is Code 1
HMapKey with time=123: This is Code 2
1
tom.bujok On

First of all, I don't know what you're trying to do when you say "I try to retrieve it".

If you use your key as in the get method everything works fine:

@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);
}

If you want to retrieve a value basing on the whole key value the HMapKey needs to implement Comparable.

Then you can query like this:

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

2
noctarius On

Hazelcast does not deserialize the keys / values and executes equals or hashCode methods but compares the serialized objects by their corresponding bytestream. If you're searching for one or more properties, please see the answer from Tom https://stackoverflow.com/a/41238649/917336