A Map is an object that stores associations between keys and values, or key/value pairs.
Given a key, you can find its value. Both keys and values are objects. The keys must be unique, but the values may be duplicated. Some maps can accept a null key and null
values, others cannot.
Interface |
Description |
Map |
Maps unique keys to values. |
Map.Entry |
Describes an element (a key/value pair) in a map. This is an inner
class of Map. |
SortedMap |
Extends Map so that the keys are maintained in ascending order. |
The Map Interface
The Map interface maps unique keys to values. A key is an object that you use to
retrieve a value at a later date. Given a key and a value, you can store the value
in a Map object. After the value is stored, you can retrieve it by using its key.
The methods declared by Map are summarized in the figure belowSeveral methods
throw a NoSuchElementException when no items exist in the invoking map. A ClassCastException is thrown when an object is incompatible with the elements
in a map. A NullPointerException is thrown if an attempt is made to use a null object
and null is not allowed in the map. An UnsupportedOperationException is thrown
when an attempt is made to change an unmodifiable map.
Methods defined in Map Interface
Maps revolve around two basic operations: get( ) and put( ). To put a value into a
map, use put( ), specifying the key and the value. To obtain a value, call get( ), passing
the key as an argument. The value is returned.
The SortedMap Interface
The SortedMap interface extends Map. It ensures that the entries are maintained
in ascending key order. The methods declared by SortedMap are summarized in
Table . Several methods throw a SuchElementException when no items are in
the invoking map. A ClassCastException is thrown when an object is incompatible
with the elements in a map. A NullPointerException is thrown if an attempt is made
to use a null object when null is not allowed in the map.
Sorted maps allow very efficient manipulations of submaps (in other words, a
subset of a map). To obtain a submap, use headMap( ), tailMap( ), or subMap( ).To
get the first key in the set,call firstKey( ). To get the last key, use lastKey( ).
The Map.Entry Interface
The Map.Entry interface enables you to work with a map entry. Recall that the entrySet( ) method declared by the Map interface returns a Set containing the map
entries. Each of these set elements is a Map.Entry object. Table summarizes the
methods declared by this interface.
Classes implementing Map Interfaces
The HashMap Class
The HashMap class uses a hash table to implement the Map interface. This allows the
execution time of basic operations, such as get( ) and put( ), to remain constant even for
large sets.
The following constructors are defined
HashMap( )
HashMap(Map m)
HashMap(int capacity)
HashMap(int capacity, float fillRatio)
The first form constructs a default hash map. The second form initializes the hash map
by using the elements of m. The third form initializes the capacity of the hash map to
capacity. The fourth form initializes both the capacity and fill ratio of the hash map by
using its arguments. The meaning of capacity and fill ratio is the same as for HashSet,
described earlier.
HashMap implements Map and extends AbstractMap. It does not add any
methods of its own.
You should note that a hash map does not guarantee the order of its elements.
Therefore, the order in which elements are added to a hash map is not necessarily the
order in which they are read by an iterator.
The following program illustrates HashMap. It maps names to account balances.
Notice how a set-view is obtained and used.
import java.util.*;
class HashMapDemo {
public static void main(String args[]) {
// Create a hash map
HashMap hm = new HashMap();
// Put elements to the map
hm.put("John Doe", new Double(3434.34));
hm.put("Tom Smith", new Double(123.22));
hm.put("Jane Baker", new Double(1378.00));
hm.put("Todd Hall", new Double(99.22));
hm.put("Ralph Smith", new Double(-19.08));
// Get a set of the entries
Set set = hm.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
// Deposit 1000 into John Doe's account
double balance = ((Double)hm.get("John Doe")).doubleValue();
hm.put("John Doe", new Double(balance + 1000));
System.out.println("John Doe's new balance: " +
hm.get("John Doe"));
}
}
Output from this program is shown here (the precise order may vary).
Todd Hall: 99.22
Ralph Smith: -19.08
John Doe: 3434.34
Jane Baker: 1378.0
Tom Smith: 123.22
John Doe’s current balance: 4434.34
The program begins by creating a hash map and then adds the mapping of names
to balances. Next, the contents of the map are displayed by using a set-view, obtained
by calling entrySet( ). The keys and values are displayed by calling the getKey( ) and getValue( ) methods that are defined by Map.Entry. Pay close attention to how the deposit
is made into John Doe’s account. The put( ) method automatically replaces any preexisting
value that is associated with the specified key with the new value. Thus, after John Doe’s
account is updated, the hash map will still contain just one “John Doe” account.
The TreeMap Class
The TreeMap class implements the Map interface by using a tree. A TreeMap provides
an efficient means of storing key/value pairs in sorted order, and allows rapid
retrieval. You should note that, unlike a hash map, a tree map guarantees that its
elements will be sorted in ascending key order.
The following TreeMap constructors are defined:
TreeMap( )
TreeMap(Comparator comp)
TreeMap(Map m)
TreeMap(SortedMap sm)
The first form constructs an empty tree map that will be sorted by using the natural order
of its keys. The second form constructs an empty tree-based map that will be sorted by
using the Comparator comp. (Comparators are discussed later in this chapter.) The third
form initializes a tree map with the entries from m, which will be sorted by using the
natural order of the keys. The fourth form initializes a tree map with the entries from sm,
which will be sorted in the same order as sm.
TreeMap implements SortedMap and extends AbstractMap. It does not define any
additional methods of its own.
The following program reworks the preceding example so that it uses TreeMap:
import java.util.*;
class TreeMapDemo {
public static void main(String args[]) {
// Create a tree map
TreeMap tm = new TreeMap();
// Put elements to the map
tm.put("John Doe", new Double(3434.34));
tm.put("Tom Smith", new Double(123.22));
tm.put("Jane Baker", new Double(1378.00));
tm.put("Todd Hall", new Double(99.22));
tm.put("Ralph Smith", new Double(-19.08));
// Get a set of the entries
Set set = tm.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
// Deposit 1000 into John Doe's account
double balance = ((Double)tm.get("John Doe")).doubleValue();
tm.put("John Doe", new Double(balance + 1000));
System.out.println("John Doe's new balance: " +
tm.get("John Doe"));
}
}
The following is the output from this program:
Jane Baker: 1378.0
John Doe: 3434.34
Ralph Smith: -19.08
Todd Hall: 99.22
Tom Smith: 123.22
John Doe’s current balance: 4434.34
Notice that TreeMap sorts the keys. However, in this case, they are sorted by first
name instead of last name. You can alter this behavior by specifying a comparator
when the map is created, as described shortly.
Comparators
Both TreeSet and TreeMap store elements in sorted order. However, it is the
comparator that defines precisely what “sorted order” means. By default, these classes
store their elements by using what Java refers to as “natural ordering,” which is
usually the ordering that you would expect. (A before B, 1 before 2, and so forth.) If
you want to order elements a different way, then specify a Comparator object when
you construct the set or map. Doing so gives you the ability to govern precisely how
elements are stored within sorted collections and maps.
The Comparator interface defines two methods: compare( ) and equals( ). The
compare( ) method, shown here, compares two elements for order:
int compare(Object obj1, Object obj2)
obj1 and obj2 are the objects to be compared. This method returns zero if the objects are
equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value
is returned. The method can throw a ClassCastException if the types of the objects are
not compatible for comparison. By overriding compare( ), you can alter the way that
objects are ordered. For example, to sort in reverse order, you can create a comparator
that reverses the outcome of a comparison.
The equals( ) method, shown here, tests whether an object equals the invoking
comparator:
boolean equals(Object obj) obj is the object to be tested for equality. The method returns true if obj and the
invoking object are both Comparator objects and use the same ordering. Otherwise, it
returns false. Overriding equals( ) is unnecessary, and most simple comparators will
not do so.
Using a Comparator
The following is an example that demonstrates the power of a custom comparator. It
implements the compare( ) method so that it operates in reverse of normal. Thus, it
causes a tree set to be stored in reverse order.
// Use a custom comparator.
import java.util.*;
// A reverse comparator for strings.
class MyComp implements Comparator {
public int compare(Object a, Object b) {
String aStr, bStr;
aStr = (String) a;
bStr = (String) b;
// reverse the comparison
return bStr.compareTo(aStr);
}
// no need to override equals
}
class CompDemo {
public static void main(String args[]) {
// Create a tree set
TreeSet ts = new TreeSet(new MyComp());
// Add elements to the tree set
ts.add("C");
ts.add("A");
ts.add("B");
ts.add("E");
ts.add("F");
ts.add("D");
// Get an iterator
Iterator i = ts.iterator();
// Display elements
while(i.hasNext()) {
Object element = i.next();
System.out.print(element + " ");
}
System.out.println();
}
}
As the following output shows, the tree is now stored in reverse order:
F E D C B A
Look closely at the MyComp class, which implements Comparator and overrides
compare( ). (As explained earlier, overriding equals( ) is neither necessary nor
common.) Inside compare( ), the String method compareTo( ) compares the two
strings. However, bStr—not aStr—invokes compareTo( ). This causes the outcome of
the comparison to be reversed.
For a more practical example, the following program is an updated version of
the TreeMap program shown earlier that stores account balances. In the previous
version, the accounts were sorted by name, but the sorting began with the first name.
The following program sorts the accounts by last name. To do so, it uses a comparator
that compares the last name of each account. This results in the map being sorted by
last name.
Hashtable:-
Hashtable was part of the original java.util and is a concrete implementation of a
Dictionary. However, Java 2 reengineered Hashtable so that it also implements the
Map interface. Thus, Hashtable is now integrated into the collections framework. It is
similar to HashMap, but is synchronized.
Like HashMap, Hashtable stores key/value pairs in a hash table. When using a
Hashtable, you specify an object that is used as a key, and the value that you want
linked to that key. The key is then hashed, and the resulting hash code is used as the
index at which the value is stored within the table.
A hash table can only store objects that override the hashCode( ) and equals( )
methods that are defined by Object. The hashCode( ) method must compute and
return the hash code for the object. Of course, equals( ) compares two objects.
Fortunately, many of Java’s built-in classes already implement the hashCode( )
method. For example, the most common type of Hashtable uses a String object as
the key. String implements both hashCode( ) and equals( ).
The Hashtable constructors are shown here:
Hashtable( )
Hashtable(int size)
The first version is the default constructor.The second version creates a hash table that
has an initial size specified by size.
// Demonstrate a Hashtable
import java.util.*;
class HTDemo {
public static void main(String args[]) {
Hashtable balance = new Hashtable();
Enumeration names;
String str;
double bal;
balance.put("John Doe", new Double(3434.34));
balance.put("Tom Smith", new Double(123.22));
balance.put("Jane Baker", new Double(1378.00));
balance.put("Todd Hall", new Double(99.22));
balance.put("Ralph Smith", new Double(-19.08));
// Show all balances in hash table.
names = balance.keys();
while(names.hasMoreElements()) {
str = (String) names.nextElement();
System.out.println(str + ": " +
balance.get(str));
}
System.out.println();
// Deposit 1,000 into John Doe's account
bal = ((Double)balance.get("John Doe")).doubleValue();
balance.put("John Doe", new Double(bal+1000));
System.out.println("John Doe's new balance: " +
balance.get("John Doe"));
}
}
The output from this program is shown here:
Todd Hall: 99.22
Ralph Smith: -19.08
John Doe: 3434.34
Jane Baker: 1378.0
Tom Smith: 123.22
John Doe’s new balance: 4434.34
Properties
Properties is a subclass of Hashtable. It is used to maintain lists of values in which the
key is a String and the value is also a String. The Properties class is used by many other
Java classes. For example, it is the type of object returned by System.getProperties( )
when obtaining environmental values.
.
Properties defines these constructors:
Properties( )
Properties(Properties propDefault)
The first version creates a Properties object that has no default values. The second
creates an object that uses propDefault for its default values. In both cases, the property
list is empty.
In addition to the methods that Properties inherits from Hashtable, Properties
defines the methods listed in Table .
The following example demonstrates Properties. It creates a property list in which
the keys are the names of states and the values are the names of their capitals. Notice
that the attempt to find the capital for Florida includes a default value.
// Demonstrate a Property list.
import java.util.*;
class PropDemo {
public static void main(String args[]) {
Properties capitals = new Properties();
Set states;
String str;
capitals.put("Illinois", "Springfield");
capitals.put("Missouri", "Jefferson City");
capitals.put("Washington", "Olympia");
capitals.put("California", "Sacramento");
capitals.put("Indiana", "Indianapolis");
// Show all states and capitals in hashtable.
states = capitals.keySet(); // get set-view of keys
Iterator itr = states.iterator();
while(itr.hasNext()) {
str = (String) itr.next();
System.out.println("The capital of " +
str + " is " +
capitals.getProperty(str)
+ ".");
}
System.out.println();
// look for state not in list -- specify default
str = capitals.getProperty("Florida", "Not Found");
System.out.println("The capital of Florida is "
+ str + ".");
}
}
The output from this program is shown here:
The capital of Missouri is Jefferson City.
The capital of Illinois is Springfield.
The capital of Indiana is Indianapolis.
The capital of California is Sacramento.
The capital of Washington is Olympia.
The capital of Florida is Not Found.
Since Florida is not in the list, the default value is used.