the Map interface
Collections; the Map interface
Collections
java.util defines a Collection interface, designed to
encompass commonalities between many classes which are collections of
objects. List is one example of a Collection; Set is another.
Collection includes the following methods, (among others), many
of which we have already used for Lists:
boolean add(Object o); // add o to this collection; return true if and
only if this collection is modified as a result (Note: if o
is
already present in the collection, the collection may choose not to add
it,
and return false. This behavior is seen in Sets.)
boolean addAll(Collection c); // add all the elements of c to this collection; return true if and only if this collection is modified as a result
void clear(); // remove all elements from this collection.
boolean contains(Object o); // return true if and only if this
collection contains o.
int size(); // return the number of elements in this collection.
boolean isEmpty(); // return true if and only if this
collection contains no elements.
Iterator iterator(); // returns an iterator over all the
elements
in the collection.
boolean remove(Object o); // removes a single instance of o from this collection if it is present.
the Map interface
One of the most common problems in computer science is to construct a lookup table. The table consists of a set of entries, each of which contains information about some entity in the application domain. For example, we might have a table of courses offered by the computer science department, a table of temperature records for cities in the United States, a table of customer records for an online bookstore, or a table of sines and cosines of angles in the back of a trigonometry textbook. In each case, the table is a two-dimensional structure in which each row represents the data associated with a particular entity (a course, a city, a customer, an angle) and each column represents a particular data attribute (instructor and room in the course table, average high and low temperatures in July in the temperature table, outsanding balance in the customer table, sine and cosine in the trig table). To implement such a table in a computer program, it would be natural to represent each entity by an object, and represent the table with a list of these objects. We would be able to use list methods to add and remove entries and to display the contents of the table by using an iterator.However, there is an important operation that is not supported by lists. That is a table lookup by key. For example, in the course table, we might like to locate a course entry given the course number. In the temperature table, we would like to locate the temperature records of a given city. In the customer table, we would like to look up the balance of a customer given the customer number. In the trig table, we would like to be able to look up the sine or cosine of a given angle. In general, the lookup operation locates an entry in a table using the value of one attribute called the search key (or just key).
The abstract data type which represents this sort of lookup table goes by several different names: Dictionary, Table, Symbol Table, Map, etc. Carrano and Savitch use the term Dictionary (see chapter 17); Java uses the term Map.
The Map interface in Java is designed to support the lookup operation. A map contains (key, value) pairs. It implements the basic operations
Object put(Object key, Object value);
Object get(Object key);
Object remove(Object key);
put inserts the given (key, value) pair in the map. If the key already exists in the map, then its value is replaced with the given value. put returns the previous value associated with the key, or null if there was none.
get searches the map for the given key. If the key is found, get returns its associated value. If the key is not found, get returns null. (Note: A map may permit the value null to be assocated with the key. In that case, a return value of null could mean either that the key is not found, or that the key is mapped to null.)
remove searches the map for the given key. If the key is found, remove removes the (key, value) pair from the map and returns the value. If the key is not found, remove returns null.
The Dictionary interface described in Carrano has some additional operations, such as
boolean contains(Object key); // returns true if and only if the given key is found in the table
Iterator getKeyIterator(); // creates and returns an iterator which iterates through the keys in the map
Iterator getValueIterator(); // creates and returns an iterator which iterates through the values in the map
boolean isEmpty(); // returns true if and only if the map is empty
void clear(); // removes all entries from the map
Map applications
Before considering how to implement a map, we can look at two simple applications of maps.example Read a text file and create a table of frequencies of occurrence of the words in the file.
public Map buildMapFromFile(BufferedReader input) throws IOException
{
static final String DELIMITERS = ",.;: \t\r\n";
Map wordTable = new /* concrete Map implementation */ ;
String line = input.readLine();
while(line != null){
line = line.toLowerCase();
StringTokenizer tokenizer = new StringTokenizer(line, DELIMITERS);
while (tokenizer.hasMoreTokens()){
String word = (String)tokenizer.nextToken();
Object value = wordTable.get(word);
if(value==null){ // word is not in the table, so add it with a count of 1
wordTable.put(word, new Integer(1));
}
else { // word is in the table, add one to its count
wordTable.put(word, new Integer(1+ ((Integer)value).intValue()));
}
} // end of while tokenizer has more tokens
line = input.readLine();
} // end of while line not null
return wordTable;
}
example Read a text file and create a concordance. For each word in the file, the concordance displays a list of the line numbers of the lines in which the word occurs.
public Map buildConcordance(BufferedReader input) throws IOException
{
static final String DELIMITERS = ",.;: \t\r\n";
Map wordTable = new /* concrete Map implementation */ ;
String line = input.readLine();
int linenum = 1;
while(line != null){
line = line.toLowerCase();
StringTokenizer tokenizer = new StringTokenizer(line, DELIMITERS);
while (tokenizer.hasMoreTokens()){
String word = (String)tokenizer.nextToken();
Object value = wordTable.get(word);
if(value==null){ // word is not in the table, so add it with a line
// number list containing the current line numberc
List list = new LinkedList();
list.add(new Integer(linenum));
wordTable.put(word, list);
}
else { // word is in the table, add current line to its line
// number list
List list = (List) value;
list.add(new Integer(linenum));
}
} // end of while tokenizer has more tokens
line = input.readLine();
++linenum;
} // end of while line not null
return wordTable;
}
Map implementations
One fundamental idea that is likely to be used in any implementation is that a Map consists of a set of map entries. Each entry contains a key and a value. The question then becomes, how should a set of map entries be managed, in order to support the basic map operations (get, put, remove).Question: How could a Map be implemented using the list techniques we have studied so far in the course: array and linked list. What would be the running times of the basic operations?
java.util provides two versions of Map: TreeMap and HashMap. TreeMap uses a binary search tree to implement the mapping; HashMap uses a hash table. We'll study both binary trees and hash tables soon.