Transcript Using Maps
Using Maps
A simple map: Hashtable
• To create a Hashtable, use:
import java.util.*;
Hashtable table = new Hashtable();
• To put things into a Hashtable, use:
table.put(key, value);
• To retrieve a value from a Hashtable, use:
value = table.get(key);
Example use of a Hashtable
import java.util.*;
public class HashtableUser {
public static void main(String[] args) {
Hashtable table = new Hashtable();
table.put("one", "un");
table.put("two", "deux");
table.put("three", "trois");
System.out.println("two -> " + table.get("two"));
System.out.println("deux -> " + table.get("deux"));
}
}
two -> deux
deux -> null
Hashtable constructors
• Hashtable()
– Constructs a new, empty hashtable with a default
capacity and load factor, which is 0.75.
• Hashtable(int initialCapacity)
– Constructs a new, empty hashtable with the specified
initial capacity and default load factor, which is 0.75.
• Hashtable(int initialCapacity, float loadFactor)
– Constructs a new, empty hashtable with the specified
initial capacity and the specified load factor.
• Hashtable(Map t)
– Constructs a new hashtable with the same mappings as
the given Map.
Which constructor should you use?
• This is basically a question of efficiency
– A hash table that is mostly empty wastes space
– If a hash table is nearly full, some searches may take a
very long time
• The initial capacity of a hash table is the number
of entries that it can hold initially
• The load factor is a measure of how full it is
– A load factor of 75% is usually a good compromise
– If the table gets fuller than the load factor, Java creates
a new, larger hash table and rehashes everything
– Rehashing is an expensive operation
Hashtable constructors (again)
• Hashtable()
– Use if the default values are good enough
• Hashtable(int initialCapacity)
– Use if you have some idea how many entries to expect
– Try to ensure it won’t be more than 75% full
– If space is not an issue, double or triple the size
• Hashtable(int initialCapacity, float loadFactor)
– Use if you are trying to be super efficient
– Requires careful experimentation and tuning
• Hashtable(Map t)
– Use to make a Hashtable from some other map
– Initial capacity = 2*(size of t), load factor = 0.75
The Collections framework
Collection
Set
Map
List
SortedMap
Hashtable
SortedSet
• Hashtable is an old (pre-Collections) class
• Hashtable has been retrofitted to implement the
Map interface
The Map interface I
• Basic operations:
– Object put(Object key, Object value)
• Returns the previous value associated with key, or null if there
was no previous value
– Object get(Object key)
• Returns null if the key was not found
• A return value of null may not mean the key was not found
(some implementations of Map allow null keys and values)
• Tests:
– boolean containsKey(Object key)
– boolean containsValue(Object value)
• Warning: probably requires linear time!
– boolean isEmpty()
– boolean equals(Object o)
• Returns true if o is also a map and has the same mappings
The Map interface II
• Optional operations:
– Object put(Object key, Object value)
• (So you could implement an immutable map)
– void putAll(Map t)
• Adds the mappings from t to this map
– void clear()
– Object remove(Object key)
• Returns the value that was associated with the key, or null
• Other:
– int size()
• Returns the number of key-value mappings
– int hashCode()
• Returns a hash code value for this map
Optional operations
• Question: How can a method declared in an
interface be optional?
• Answer: you have to implement it, but the
implementation may be something like this:
public void remove(Object key)
throws UnsupportedOperation Exception {
throw new UnsupportedOperationException();
}
• In fact, HashMap extends AbstractMap, which
provides many of the map operations, and
implements the optional operations like this
Map views
• Set keySet()
– Returns a set view of the keys contained in this map.
• Collection values()
– Returns a collection view of the values contained in this map
– Can’t be a set—keys must be unique, but values may be repeated
• Set entrySet()
– Returns a set view of the mappings contained in this map.
• A view is dynamic access into the Map
– If you change the Map, the view changes
– If you change the view, the Map changes
• The Map interface does not provide any Iterators
– However, there are iterators for the above Sets and Collections
Map.Entry: Interface for
entrySet elements
• public interface Entry {
Object getKey( );
Object getValue( );
Object setValue(Object value);
}
• This is a small interface for working with the
Collection returned by entrySet( )
• Can get elements only from the Iterator, and
they are only valid during the iteration
Constructors
• Map is an interface, so it cannot require any
constructors
• However, Java always supplies:
– A no-argument constructor for each Map type
– A constructor that takes a Map argument, and copies its
key-value pairs into the new Map
• If you ever implement your own Map class, you
should define these constructors
– Defining your own Map class is easy:
class MyMap implements Map { ... }
– There are, however, a lot of methods to implement
Hazards I
• In order for a Hashtable to work correctly,
– equals must be defined properly on the keys
– hashCode must be defined properly on the keys
• This is not a problem if you use Strings for the
keys (this is extremely common)
• If you use objects of some other class as your
keys, you must make sure equals and hashCode are
properly defined
• Note: equals and hashCode are properly defined for
all of Java’s Maps; it’s the keys that you need to be
careful with
Hazards II
• You should use immutable objects (like Strings) as
keys
• If you put a value into a hash table with a mutable key,
and you change the key, what happens?
– Answer: Nothing good!
• Special case #1: A map may not contain itself as a key
• Special case #2: A map may contain itself as a value,
but equals and hashCode are no longer well-defined
• These special cases are really weird and you will
probably never get anywhere near them
From Hashtables to HashMaps
• Hashtable has been around a long time, but
HashMap is new with Java 1.2
• So why am I teaching you the old stuff?
– Actually, except for the constructors, I’ve been talking
about the Map interface, which both Hashtable and
HashMap implement
– Both are cloneable (more on this later) and serializable
• Differences:
– Hashtable is synchronized; HashMap is not
– HashMap permits null values and (one) null key;
Hashtable does not
synchronized
• Java supports multiple Threads
– A Thread is an execution sequence
– Having multiple Threads means that Java appears to be
doing many different things all at the same time
– Threads can interfere with each other unless they are
carefully synchronized (prevented from both using the
same data at the same time)
– This can be an issue with GUIs, which run in a different
Thread from the rest of the program
– If you use a hash table from an event handler, use a
Hashtable (which is synchronized) instead of a
HashMap (which is not)
• I hope to have time to give a decent lecture on
Threads and synchronization
Copying objects
• In Java, you seldom copy objects, you just copy
references to objects
Person mary = new Person("Mary", 21);
Person john = new Person("John", 23, mary);
mary.setSpouse(john);
Person jack = john;
jack.name = "Jack";
john
jack
"John"
"Jack"
23
"Mary"
"John"
21
• Suppose, however, that you really do want to make a copy;
how do you do it?
• Answer: you clone the object
The Cloneable interface
• Cloneable, like Serializable, is a marker interface: it doesn't
require any methods
• It does, however, allow you to use the clone method
• class Person implements Cloneable { ... }
...
Person jack = john.clone();
"John"
• clone()
makes a shallow copy
• If you want a deep
john
copy, you have to
write a lot more code
jack
• Avoid making copies
if possible; it’s not
easy and it’s expensive
23
"John"
23
"Mary"
"John"
21
The SortedMap interface
• A hash table keeps elements in an (apparently)
random order
• Sometimes you want the keys of a map to be in
sorted order (e.g. phone book, dictionary)
• A map can be implemented with a hash table, but
it doesn’t have to be
• The SortedMap interface implements the Map
interface and provides additional methods
• For efficiency, you want an implementation that
keeps its elements in some kind of order
Requirements for SortedMap
• A SortedMap keeps its elements in the order of
increasing key values
• Therefore, it must be possible to sort the keys!
• This means:
– The keys must be objects of a type that implement the
Comparable interface (or be given a Comparator)
– Keys must be mutually comparable (e.g. you can’t
compare a String to a Button)
– The ordering must be consistent with equals
• All implementations of SortedMap should supply
four constructors
– We’ll see an example of these shortly
SortedMap Methods I
• Comparator comparator()
– Returns the comparator associated with this sorted map,
or null if it uses its keys' natural ordering.
• Object firstKey()
– Returns the first (lowest) key currently in this sorted
map.
• Object lastKey()
– Returns the last (highest) key currently in this sorted
map.
SortedMap Methods II
• SortedMap headMap(Object toKey)
– Returns a view of the portion of this sorted map whose
keys are strictly less than toKey.
• SortedMap subMap(Object fromKey,
Object toKey)
– Returns a view of the portion of this sorted map whose
keys range from fromKey, inclusive, to toKey,
exclusive.
• SortedMap tailMap(Object fromKey)
– Returns a view of the portion of this sorted map whose
keys are greater than or equal to fromKey.
The TreeMap class
• TreeMap implements SortedMap
• TreeMap is the only implementation that Java
provides for SortedMap
• Question: Since there’s only one implementation,
why bother to have a separate interface?
• Answer: To give you the flexibility to define
additional kinds of sorted map, if you wish to
– You probably won’t—but the flexibility is there
TreeMap constructors
• TreeMap()
– Constructs a new, empty map, sorted according to the keys' natural
order.
• TreeMap(Comparator c)
– Constructs a new, empty map, sorted according to the given
comparator.
• TreeMap(Map m)
– Constructs a new map containing the same mappings as the given
map, sorted according to the keys' natural order.
• TreeMap(SortedMap m)
– Constructs a new map containing the same mappings as the given
SortedMap, sorted according to the same ordering.
Quick summary
• Interfaces (cannot instantiate):
–
–
–
–
Map
SortedMap
Serializable
Cloneable
• Classes (can instantiate):
– Hashtable
– HashMap
– TreeMap
• As always, it’s best to avoid exposing the implementation;
hence:
– Map myMap = new HashMap();
• But probably not:
– Map myMap = new TreeMap();
Sets
• We’ve talked about Sets before, and you probably
remember the basic operations:
– int size( );
boolean isEmpty( );
boolean contains(Object e);
boolean add(Object e);
boolean remove(Object e);
Iterator iterator( );
• However, Set is an interface, not a class
• There are two supplied implementations: HashSet
(for when you don’t care about the order of
elements) and TreeSet (for when you do)
• These are implemented by HashMap and
TreeMap, respectively
The End