DeviceObjectPropertyReference hashCode function collision
-
The current DeviceObjectPropertyReference hashCode implementation appears to not generate unique hashes.
Take for example the following:
DeviceObjectPropertyReference dopr1 = new DeviceObjectPropertyReference(new ObjectIdentifier(ObjectType.analogValue, 65), PropertyIdentifier.presentValue, null, new ObjectIdentifier(ObjectType.device, 1002)); DeviceObjectPropertyReference dopr2 = new DeviceObjectPropertyReference(new ObjectIdentifier(ObjectType.analogValue, 3), PropertyIdentifier.presentValue, null, new ObjectIdentifier(ObjectType.device, 1004)); System.out.println(dopr1.hashCode()); System.out.println(dopr2.hashCode());
Both return a value of 987574618.
The javadocs for the hashCode() function state:
It is not required that if two objects are unequal according to the java.lang.Object.equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
So technically this isn't a bug, but I don't so how anyone can reliably depend on the result of this function for anything useful (like using it as a key in a hashmap as I was). -
Search for "why are hashes useful": http://stackoverflow.com/questions/506029/whats-the-purpose-in-hashing-information
-
I am a bit confused by your response.
Looking at the top answer at the link you provided, they list 4 reasons.
1 - "Used to compare large amounts of data". Not really applicable here
2 - "Hashes can be used to index data". Yes! That's what I attempted, but when two different objects property references produce the same hash, it cannot be used as an index
3 - "They can be used in cryptographic applications like digital signatures". Not applicable.
4 - "Hashing can be used to generate seemingly random strings". Not really applicable here.Looking at the second answer, the reason they describe as to why I would use a hash table is exactly what I was doing.
So, expanding on my original code:
DeviceObjectPropertyReference dopr1 = new DeviceObjectPropertyReference(new ObjectIdentifier(ObjectType.analogValue, 65), PropertyIdentifier.presentValue, null, new ObjectIdentifier(ObjectType.device, 1002)); DeviceObjectPropertyReference dopr2 = new DeviceObjectPropertyReference(new ObjectIdentifier(ObjectType.analogValue, 3), PropertyIdentifier.presentValue, null, new ObjectIdentifier(ObjectType.device, 1004)); HashMap<Integer, Encodable> propertyValues = new HashMap<Integer, Encodable>(); Real value1 = new Real(20.0f); Real value2 = new Real(30.0f); propertyValues.put(dopr1.hashCode(), value1); propertyValues.put(dopr2.hashCode(), value2); System.out.println("Value1=" + propertyValues.get(dopr1.hashCode())); System.out.println("Value2=" + propertyValues.get(dopr2.hashCode())); ```In theory, it should print out Value1=20.0 Value2=30.0 but it actually prints Value1=30.0 Value2=30.0
-
You misinterpreted what they said. You had said you didn't know what hashes might be good for, and i provided an answer. You were using them inappropriately: as a unique key, rather than an indexing key, which are two different things. Since a hash is not guaranteed to be unique, you obviously should not use it for such a purpose.
That said, you need to reconsider what you can use as a unique key, if that is what you need. This is a question for you to decide. I don't know your application, and so can't really help.