0

I am trying to complete a task that in my hash map, I only store the KV proxy object which the actual data is storing off heap.

So I create a proxy object which override equals and hashcode method to make it have the same value with the origin object.

Then I test the result and find that I can not find the V again by the origin key.

ObjectOffHeapProxy offHeapKeyProxy = new ObjectOffHeapProxy(key);
System.out.println("key="+key+"---offHeapKeyProxy.hashCode()==key.hashCode() "+(offHeapKeyProxy.hashCode()==key.hashCode()));
System.out.println("key="+key+"---offHeapKeyProxy.equals(key) "+(offHeapKeyProxy.equals(key)));
ObjectOffHeapProxy offHeapValueProxy = new ObjectOffHeapProxy(value);
skeleton.put(offHeapKeyProxy,offHeapValueProxy);
//put into the map
System.out.println("put by proxy,try get object from the origin key is :" + skeleton.get(key));
//can't find it again.
System.out.println("put by proxy,try get object from the proxy is"+skeleton.get(offHeapKeyProxy));
bloomFilter.add(key.hashCode());
System.out.println("put a proxy,try get object from the proxy is"+skeleton.get(offHeapKeyProxy));
//this works but it does not meet my expectation

OUTPUT is like:

key=1---offHeapKeyProxy.hashCode()==key.hashCode() true
key=1---offHeapKeyProxy.equals(key) true
put a proxy,try get object from the origin key is :null
put a proxy,try get object from the 
proxy isxxx.yyy.ObjectOffHeapProxy@b73a019f

In my opinion , the hashcode is to find the bucket position, and they will use equals to determine if they the equals , and since hashcode are the same and they are equals(), why is that?

FYI:

public class ObjectOffHeapProxy {

    private final ByteBuffer buff;
    public ObjectOffHeapProxy(Object actual) throws IOException {

        byte[] bytes = SerialUtil.serialize(actual);
        this.buff = ByteBuffer.allocateDirect(bytes.length);
        buff.put(bytes);
    }


    @Override
    public boolean equals(Object o) {
        return findActual().equals(o);
    }

    /**
     * actual data's hashcode
     * @return
     */
    @Override
    public int hashCode() {
        return findActual().hashCode();
    }

    public Object findActual() {
        try{
            buff.flip();
            byte[] target = new byte[buff.limit()];
            buff.get(target);
            return SerialUtil.deserialize(target);//TODO  please check
        }
        catch (IOException | ClassNotFoundException ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

} 

UPDATE

Just as the comments point out, equals break things:

System.out.println("key="+key+"---offHeapKeyProxy.hashCode()==key.hashCode() "+(offHeapKeyProxy.hashCode()==key.hashCode()));
System.out.println("key="+key+"---offHeapKeyProxy.equals(key) "+(offHeapKeyProxy.equals(key)));
System.out.println("key="+key+"---key.equals(offHeapKeyProxy) "+(key.equals(offHeapKeyProxy)));  //false here!!!!

But since I have no idea to make change to the key, they are from the user, how can I solve it?

Chetan Joshi
  • 5,582
  • 4
  • 30
  • 43
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149
  • Did you mutate the key while it was in the map? That breaks things. – user2357112 Mar 15 '17 at 05:42
  • I should have not, please check the code, I just put it and get from it, so it should not. – JaskeyLam Mar 15 '17 at 05:42
  • 3
    It looks like your `equals` isn't symmetric. Your proxy thing considers itself equal to the thing it proxies, but not vice versa. That also breaks things. – user2357112 Mar 15 '17 at 05:43
  • @user2357112 Yes!!!!, I just find out this too!! How could I solve it, since hashmap since using the opposite way – JaskeyLam Mar 15 '17 at 05:44
  • Duplicate of http://stackoverflow.com/questions/30488622/implementing-equals-with-jdk-dynamic-proxies. No answer there though. – kennytm Mar 15 '17 at 05:46
  • Instead of calling `get` with your "real" object, call it with another proxy, one that understands the proxies in the map (and which is understood by the proxies in your map). You may need to introduce another proxy class for this to work, or your existing one could fit. – user2357112 Mar 15 '17 at 05:49
  • I agree, I am considering to make the key as a `proxyWithEqualsTrick` to make it equals when `proxy.equals(actual) || actual.equals(proxy)`, any advice or risk for this? – JaskeyLam Mar 15 '17 at 05:52
  • Two quick thoughts: 1. A common abstract superclass for real object and proxy could make it easier to create a symmetric `equals` method. 2. Could you use a `TreeMap` with a comparator that deems real object and proxy equal? – Ole V.V. Mar 15 '17 at 06:34

0 Answers0