CSDN博客

img CanFly

Utilizing the Map Interface from the Collections Framework

发表于2002/4/8 9:25:00  812人阅读

分类: java

Utilizing the Map Interface from the Collections Framework


by Ming Chou


We want to hear from you! Please send us your feedback.


1. Introduction
2. Map Interface
3. Map Implementations
3.1 java.util.HashTable Implementation
3.2 java.util.HashMap Implementation
3.3 java.util.TreeMap Implementation
4. Map Examples
4.1 HashMap Example
4.2 TreeMap Example
5. Conclusion

The following Technical Article may contain actual software programs in source code form. This source code is made available for developers to use as needed, pursuant to the terms and conditions of this license.


    1. Introduction


    With the introduction of the Collections Framework in the Java[tm] 2 Platform, Standard Edition, several commonly used data structure interfaces were integrated into the Java[tm] 2 SDK to simplify the programmer's job, and to allow the programmer to focus on business requirements rather than building data objects. This new framework provides several useful tools and functionality to the user that do not require the user to know much about the details of the framework.

    Within the Java[tm] Collections Framework, there are two main interfaces, (1) the Collection interface, which includes the list and set interfaces, and (2) the Map interface. The main difference between the Collection and the Map interfaces is that a Collection stores a group of Objects, while Maps hold key/value pairs of data. In a Map Object, each key has at most one associated value. A perfect everyday example of when to use a Map would be to correlate a person's profile with their social security number. The social security number would be the key, while the profile would be the corresponding person's mapped "value".



    2. The Map Interface


    The following code snippet shows what the Map interface looks like:
    public interface java.util.Map {

    //Altering Methods
    public Object put(Object key, Object value); //gets Object with key/value mapping
    public Object remove(Object key); //removes Object with key
    public void putAll(java.util.Map); //put all Map elements into current Map
    public void clear(); //removes all mappings from current Map

    //Querying Methods
    public Object get(Object key); //gets Object with key
    public int size(); //returns number of Map elements
    public boolean isEmpty(); //check if Map is empty
    public boolean containsKey(Object); //Checks if map contains object as key
    public boolean containsValue(Object); //Checks if map contains object as value
    public boolean equals(Object); //compares specified Object with current Map

    //Viewing Methods
    public java.util.Set keySet(); //Gets keys
    public java.util.Collection values(); //Gets values
    public java.util.Set entrySet(); //Gets mappings

    public static interface java.util.Map.Entry { //a map-entry (single key/value pair)
    public Object getKey(); //returns current entry key
    public Object getValue(); //returns current entry value
    public Object setValue(Object value); //replaces current value with specified value
    public boolean equals(Object); //compares current object with specified object
    public int hashCode(); //returns hashcode with current map-entry
    }
    }

    The Map interface provides us with methods to accomplish three main functionalities:


    1. Map Altering

    2. Map Querying

    3. Map Viewing

    Map altering methods allow the user to alter the contents of the current Map. This includes the removal, updating, and insertion of key/value pairs.

    Map querying methods allow the user to retrieve key/value pairs from the Map. Not only are there methods to query the contents of Map elements, but there are also methods that can be used to query the entire Map Object.

    There are three different views which can be used to analyze Map key/value Objects. Since the keys in a map must be unique, the keyset() method retrieves a Set of the keys in the Map (A Set is a collection of unique data elements). The values() method returns a Collection of the value Objects (A Collection is a group of objects which allows the storage of duplicate objects). The entrySet() method returns a Set of Map.Entry mappings.

    The Map.Entry interface is the object used to store a single key/value pair. Within the Map.Entry, there are methods to store and retrieve individual key/value elements. The entrySet() method returns a Set of objects that implements the Map.Entry interface. Each element within the Set represents a single key/value pair in the Map.



    3. Map Implementations


    The following section will provide a brief overview of three commonly used map implementations:

    1. java.util.Hashtable
    2. java.util.HashMap
    3. java.util.TreeMap




      3.1 java.util.Hashtable Implementation


      The Hashtable Object maps key objects to value objects. Methods are provided to enable a quick lookup of values based upon a key search. The Hashtable Object was introduced in Java 1.0 platform, while the HashMap Object which is introduced in the next section was introduced in the Java 1.2 platform platform. The additional methods the Hashtable implementation offers (not including those in the Map interface) are:
      public class java.util.Hashtable extends Dictionary implements Cloneable, Map, Serializable {

      //Hashtable constructors
      public Hashtable(); //construct a default Hashtable with default capacity and load of 0.75
      public Hashtable (int initialCapacity); //construct a Hashtable with passed capacity and default load of 0.75
      public Hashtable(int initialCapacity, float load); //construct Hashtable with passed capacity and load
      public Hashtable(Map); //construct Hashtable with passed mapping

      //Hashtable specific methods
      public boolean contains(Object); //checks if Object is in Hashtable
      public Enumeration elements(); //returns Enumeration of elements in Hashtable
      public Enumeration keys(); //returns Enumeration of keys in hashtable
      public Object clone(); //creates shallow copy of Hashtable(structure copied, but not key/values)
      public String toString(); //prints out key/value pairs of Hashtable elements
      protected void rehash(); //reorganizes all elements in Hashtable, and increases Hashtable capacity

      public Object get(Object); //get Value from passed in key
      public Object put(Object key, Object value); //insert key/value pair

      }

      A Hashtable is similar to a regular table where keys are mapped to values, but the Hashtable offers a quick way to retrieve data. When an element is inserted into the Hashtable, the name of the Object is hashed and the resulting integer value from the hash is used as the table index for that Object. The Object is then stored as the value of the cell the hash index is referring to. If another Object with the same name is stored into the Hashtable, the extra Objects are stored in a linked list following the original item.

      The initial capacity of the Hashtable dictates how many spaces are allocated for Objects in the Hashtable. As a Hashtable is a dynamic entity, constant resizing is required to efficiently allocate space for the Hashtable. The load factor indicates how full percentage wise the Hashtable is allowed to become before the Hashtable's capacity is automatically increased.

      Two things to note are that (1) Hashtable data is synchronized and (2) the null value is not allowed as a key or value in the Hashtable.


      3.2 java.util.HashMap Implementation


      The HashMap is very similar to the Hashtable, but was introduced recently starting with the Java 1.2 platform. There are two main differences between HashMap and Hashtable. First, the HashMap is not synchronized (making access faster), and second, the HashMap allows null values to be used as values or keys, which are disallowed in the Hashtable implementation. HashMap specific methods (not found in the Map interface) are:
      public class java.util.HashMap implements Map, Cloneable, java.io.Serializable {

      public HashMap(int initialCapacity, float load); //construct a default HashMap with default capacity and load of 0.75
      public HashMap(int initialCapacity); //construct a HashMap with passed capacity and default load of 0.75
      public HashMap(); //construct HashMap with passed capacity and load
      public Hashmap(Map); //construct HashMap with passed mapping

      public Object clone(); //constructs shallow copy of HashMap (keys/values not copied)

      public Object get(Object); //get Value from passed in key
      public Object put(Object key, Object value); //insert key/value pair



      }


      The HashMap, after being introduced in the Java 1.2 platform platform, has provided much better performance than the Hashtable. Though HashMap is not synchronized, it can be made synchronized. What happens if the HashMap is modified in a multi-threaded environment? The HashMap has a fail-fast iterator. Fail-fast means that the iterator is notified when the underlying collection changes, and essentially causes the fetching of the next element to fail by throwing ConcurrentModificationException.


      3.3 java.util.TreeMap Implementation


      The TreeMap implementation implements the Map interface but stores elements in a tree. The TreeMap has a little bit more overhead during operation than the HashMap, but because of the tree structure, it returns keys in sorted order. If there is no need to retrieve Map elements sorted by key, then the HashMap would be a more practical structure to use. The TreeMap implemented public members not included in the Map interface are:
      public class java.TreeMap implements SortedMap, Cloneable, java.io.Serializable {

      public TreeMap(); //new TreeMap
      public TreeMap(Comparator); //new TreeMap using Comparator
      public TreeMap(Map); //new TreeMap using Map
      public TreeMap(SortedMap); //new TreeMap using sortedMap

      public Comparator comparator();
      public Object firstKey(); //returns first Key
      public Object lastKey(); //returns last Key
      public Object clone(); //returns shallow copy of TreeMap

      public SortedMap headMap(Object); //returns SortedMap of all elements upto Object
      public SortedMap tailMap(Object); //returns SortedMap of all elements after Object
      public SortedMap subMap(Object, Object); //returns SortedMap of all elements between keys

      public Object get(Object); //get Value from passed in key
      public Object put(Object key, Object value); //insert key/value pair
      }



      The TreeMap is very useful when you need to store objects in some sort of order. For example, a phone book or storing the words in a dictionary would be ideal candidates for usage with a TreeMap. SortedMap is a subinterface of Map. TreeMap is the only implementation that utilizes the SortedMap interface.




    4. Examples


    In the following section, two examples will be presented, the first will show an example of a HashMap, while the second will utilize the TreeMap. Notice that the only difference in the code is present in one line only, when the calendar Map is instantiated, yet the outputs are completely different due to the difference in storage behavior of TreeMap and HashMap.



      4.1 HashMap Example


      import java.util.*;

      public class ExampleHashMap {

      //calendar Map
      Map calendar = new HashMap();

      //constructor to add all elements into Map
      public ExampleHashMap(String d[], String i[]){
      for (int x=0; x<d.length; x++)
      calendar.put(d[x], i[x]);
      }


      //main method
      public static void main(String args[]) {

      //Data to be inserted into calendar
      String [] dates = {"10/31/01", "01/01/01", "03/05/01", "02/04/01"};
      String [] items = {"Halloween", "New Years", "Birthday", "Anniversary"};

      //create instance of class
      ExampleHashMap example = new ExampleHashMap(dates, items);

      //print out all key/value pairs in map
      System.out.println("map= " + example.calendar);

      //retrieve mappings into Set
      Set mappings = example.calendar.entrySet();

      System.out.println("object /t/t/tkey/t/tvalue");
      //iterate through mappings and print content
      for (Iterator i = mappings.iterator(); i.hasNext();) {
      Map.Entry me = (Map.Entry)i.next();
      Object ok = me.getKey();
      Object ov = me.getValue();
      System.out.print(me + "/t");
      System.out.print(ok + "/t");
      System.out.println(ov);
      }

      }


      }


      -Output of HashMap (each compiler will output results in different order):

        /tmp> java ExampleHashMap
        map= {01/01/01=New Years, 03/05/01=Birthday, 02/04/01=Anniversary, 10/31/01=Halloween}
        object key value
        01/01/01=New Years 01/01/01 New Years
        03/05/01=Birthday 03/05/01 Birthday
        02/04/01=Anniversary 02/04/01 Anniversary
        10/31/01=Halloween 10/31/01 Halloween


      Notice how the objects stored into the HashMap were not stored in chronological order, nor in alphabetical order. The output order actually depends upon which compiler is being used, and the machine settings. Halloween was actually the first object "put" into the HashMap, but was actually stored in the last mapping in the HashMap.


      4.2 TreeMap Example

      import java.util.*;

      public class ExampleTreeMap {

      //calendar Map
      Map calendar = new TreeMap();

      //constructor to add all elements into Map
      public ExampleTreeMap(String d[], String i[]){
      for (int x=0; x<d.length; x++)
      calendar.put(d[x], i[x]);
      }


      //main method
      public static void main(String args[]) {

      //Data to be inserted into calendar
      String [] dates = {"10/31/01", "01/01/01", "03/05/01", "02/04/01"};
      String [] items = {"Halloween", "New Years", "Birthday", "Anniversary"};

      //create instance of class
      ExampleTreeMap example = new ExampleTreeMap(dates, items);

      //print out all key/value pairs in map
      System.out.println("map= " + example.calendar);

      //retrieve mappings into Set
      Set mappings = example.calendar.entrySet();

      System.out.println("object /t/t/tkey/t/tvalue");
      //iterate through mappings and print content
      for (Iterator i = mappings.iterator(); i.hasNext();) {
      Map.Entry me = (Map.Entry)i.next();
      Object ok = me.getKey();
      Object ov = me.getValue();
      System.out.print(me + "/t");
      System.out.print(ok + "/t");
      System.out.println(ov);
      }

      }


      }



      -Output of TreeMap:

        /tmp> java ExampleTreeMap
        map= {01/01/01=New Years, 02/04/01=Anniversary, 03/05/01=Birthday, 10/31/01=Halloween}
        object key value
        01/01/01=New Years 01/01/01 New Years
        02/04/01=Anniversary 02/04/01 Anniversary
        03/05/01=Birthday 03/05/01 Birthday
        10/31/01=Halloween 10/31/01 Halloween


      Output from the TreeMap object is a little more predictable than the HashMap. Notice that Mappings were sorted in alphabetical order by the key value. Unlike the HashMap output, the TreeMap output would be more useful in a real world calendar application. One drawback of using the TreeMap data structure as mentioned earlier is that there is overhead when you "put" or "remove" elements from the TreeMap structure due to sorting, which can affect program performance.




    5. Conclusion


    The Map interface and the different implementations offered as part of the Collections package provide a convenient way to store key/value objects. The general rule when considering which implementation to utilize is to use TreeMap when element ordering is important, and use HashMap when elements do not need to be stored in any particular order. Using Hashtable is generally discouraged since HashMap provides all similar functionality, and generally runs quicker. HashMaps can also be made synchronized if you are using the HashMap in a multi-threaded environment.
0 0

相关博文

我的热门文章

img
取 消
img