Tuesday, December 25, 2012

Collections : Keys in a Map 3 And Final

Finally this post is about the class which is immutable and can be a valid key in a Map. We would correct both the approaches we have discussed earlier. The first where we had a setter method. And the second where the class could be manipulated by an inheritor class.

    /**
     *
     *
     * @author Sanjay
     *
     */
    static interface Key {
        /**
         *
         *
         * @return
         */
        public String getKey();
    }
 

First we define the interface using which we will put the keys in the Map. As the reader can see the interface needs a single method to be implemented for its children. The getKey() method which returns a property (essentially a state holding property) of type String.

Next we have two classes implementing this interface using their different approaches.

The first implementer.

 

    /**
     *
     * Valid because the setter property has been eliminated and the state holding property is private making the class immutable.
     *
     * @author Sanjay
     *
     */
    static class ValidKey1 implements Key {
        private String key;

        /**
         *
         *
         * @return
         */
        public String getKey() {
            return key;
        }

        /**
         *
         *
         * @param key
         */
        public ValidKey1(String key) {
            super();
            this.key = key;
        }
      
        /**
         *
         * We re-use the String equals
         *
         */
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Key) {
                if(((Key)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 second implementer.

 

/**
     *
     * Valid because although the class can be extended and its inheritors can access the state changing property it can be overridden as it is a final property and is set through the Constructor.
     *
     * @author Sanjay
     *
     */
    static class ValidKey2 implements Key {
        protected final String key;

        /**
         *
         *
         * @return
         */
        public String getKey() {
            return key;
        }

        /**
         *
         *
         * @param key
         */
        public ValidKey2(String key) {
            this.key = key;
        }
      
        /**
         *
         * We re-use the String equals
         *
         */
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Key) {
                if(((Key)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 second Implementer can be extended but the state holding property cannot be overriden.

 

/**
     *
     * @author Sanjay
     *
     */
    static class ValidKey3 extends ValidKey2 {
      
        /**
         *
         *
         * @param key
         */
        public ValidKey3(String key) {
            // TODO Auto-generated constructor stub
            super(key);
        }
      
        public void setKey(String key) {
//            super.key = key; // this DOES NOT COMPILE
        }
    }





The client code calling the above is below.

 

package org.home.project21.study.designPatterns;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * Collections : Keys in a Map 3 And Final
 *
 *
 * @author Sanjay
 *
 */
public class CollectionsTest3 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Map myMap = new HashMap();
        Key iKey = new ValidKey1("ValidKey");
        Key iKeyRef = new ValidKey3("ValidKey"); // 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");                       this DOES NOT COMPILE
      
        System.out.println(" myMap has  " + myMap.get(iKeyRef) + " against this key " + iKeyRef.toString());// this will print the correct value

      
    }



The final output is below. as one can see here we are able to both put and retrieve the values in the Map.

 

myMap has This is Value against this key ValidKey 
myMap has This is Value against this key ValidKey

No comments: