Some time ago I was needed to write my own custom classes for keys in Maps. That brought me to the concept of immutable classes which are needed to be valid keys in a Map.
Let us look at the code below. It is an inner class which has a state-holding property of type String which is set through the Constructor. In addition to that it overrides the methods with which the HashMap or any other implementation of Map would 'bucket' it and check the equality with a future retrieval.
The problem with the above class is that the setter method with the javadoc comment
Let us look at the code below. It is an inner class which has a state-holding property of type String which is set through the Constructor. In addition to that it overrides the methods with which the HashMap or any other implementation of Map would 'bucket' it and check the equality with a future retrieval.
/**
*
* Invalid because this has a mutable property key of type String. It is mutable as it has a setter method.
*
* @author Sanjay
*
*/
static class InvalidKey {
private String key;
/**
*
*
* @return
*/
public String getKey() {
return key;
}
/**
* The spoiler method
*
* @param key
*/
public void setKey(String key) {
this.key = key;
}
/**
*
*
* @param key
*/
public InvalidKey(String key) {
super();
this.key = key;
}
/**
*
* We re-use the String equals
*
*/
@Override
public boolean equals(Object obj) {
if(obj instanceof InvalidKey) {
if(((InvalidKey)obj).getKey().equals(this.key)) return true;
else return false;
}
else return false;
}
/**
*
* We re-use the Object hashCode and the String code hashCode if the key is not null.
*
*/
@Override
public int hashCode() {
if(key!=null) return this.key.hashCode(); // we simply return String's hash code
return super.hashCode(); // if key is null then we return the Object's hash code value.
}
/**
*
*
*/
public String toString() {
StringBuffer buffer = new StringBuffer("");
buffer.append(this.key);
return buffer.toString();
}
}
The problem with the above class is that the setter method with the javadoc comment
Spolier method can be used to reset the Key after the Map has been modified with this key. An example of the use will elucidate the problem. package org.home.project21.study.designPatterns;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* Collections : Keys in a Map 1
*
*
*
* @author Sanjay
*
*/
public class CollectionsTest1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Map myMap = new HashMap();
InvalidKey iKey = new InvalidKey("InvalidKey1");
InvalidKey iKeyRef = new InvalidKey("InvalidKey1"); // creating a new key with the same value
myMap.put(iKey, "This is Value");
iKey = null; // we remove the link from the first reference to the Object
System.out.println(" myMap has " + myMap.get(iKeyRef) + " against this key " + iKeyRef.toString());// this will print the correct value
iKeyRef.setKey("InvalidKey2");
System.out.println(" myMap has " + myMap.get(iKeyRef) + " against this key " + iKeyRef.toString());// this will print the correct value
}
The following is the output of the Program.
myMap has This is Value against this key InvalidKey1 myMap has null against this key InvalidKey2
As can be seen from the output the key is unable to retrieve the Value from the Map as the Object is mutable and has it's state changed. So the equality test fails and hence a null is returned.
No comments:
Post a Comment