Using Maps A simple map Hashtable To create
Using Maps
A simple map: Hashtable • To create a Hashtable, use: import java. util. *; Hashtable = 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 1. import java. util. *; public class Hashtable. User { public static void main(String[] args) { Hashtable = 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")); } } 2. two -> deux -> null
Hashtable constructors • Hashtable() – Constructs a new, empty hashtable with a default capacity and load factor, which is 0. 75. • Hashtable(int initial. Capacity) – Constructs a new, empty hashtable with the specified initial capacity and default load factor, which is 0. 75. • Hashtable(int initial. Capacity, float load. Factor) – 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 initial. Capacity) – 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 initial. Capacity, float load. Factor) – 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 Sorted. Map Hashtable Sorted. Set • 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 contains. Key(Object key) – boolean contains. Value(Object value) • Warning: probably requires linear time! – boolean is. Empty() – 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 put. All(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 hash. Code() • 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 Unsupported. Operation Exception { throw new Unsupported. Operation. Exception(); } • In fact, Hash. Map extends Abstract. Map, which provides many of the map operations, and implements the optional operations like this
Map views • Set key. Set() – 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 entry. Set() – 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 entry. Set elements • public interface Entry { Object get. Key( ); Object get. Value( ); Object set. Value(Object value); } • This is a small interface for working with the Collection returned by entry. Set( ) • 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 My. Map 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 – hash. Code 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 hash. Code are properly defined • Note: equals and hash. Code 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 hash. Code are no longer well-defined • These special cases are really weird and you will probably never get anywhere near them
From Hashtables to Hash. Maps • Hashtable has been around a long time, but Hash. Map 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 Hash. Map implement – Both are cloneable (more on this later) and serializable • Differences: – Hashtable is synchronized; Hash. Map is not – Hash. Map 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 Hash. Map (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. set. Spouse(john); Person jack = john; jack. name = "Jack"; john jack "Jack" "John" 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 Sorted. Map 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 Sorted. Map 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 Sorted. Map • A Sorted. Map 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 Sorted. Map should supply four constructors – We’ll see an example of these shortly
Sorted. Map Methods I • Comparator comparator() – Returns the comparator associated with this sorted map, or null if it uses its keys' natural ordering. • Object first. Key() – Returns the first (lowest) key currently in this sorted map. • Object last. Key() – Returns the last (highest) key currently in this sorted map.
Sorted. Map Methods II • Sorted. Map head. Map(Object to. Key) – Returns a view of the portion of this sorted map whose keys are strictly less than to. Key. • Sorted. Map sub. Map(Object from. Key, Object to. Key) – Returns a view of the portion of this sorted map whose keys range from. Key, inclusive, to to. Key, exclusive. • Sorted. Map tail. Map(Object from. Key) – Returns a view of the portion of this sorted map whose keys are greater than or equal to from. Key.
The Tree. Map class • Tree. Map implements Sorted. Map • Tree. Map is the only implementation that Java provides for Sorted. Map • 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
Tree. Map constructors • Tree. Map() – Constructs a new, empty map, sorted according to the keys' natural order. • Tree. Map(Comparator c) – Constructs a new, empty map, sorted according to the given comparator. • Tree. Map(Map m) – Constructs a new map containing the same mappings as the given map, sorted according to the keys' natural order. • Tree. Map(Sorted. Map m) – Constructs a new map containing the same mappings as the given Sorted. Map, sorted according to the same ordering.
Quick summary • Interfaces (cannot instantiate): – – Map Sorted. Map Serializable Cloneable • Classes (can instantiate): – Hashtable – Hash. Map – Tree. Map • As always, it’s best to avoid exposing the implementation; hence: – Map my. Map = new Hash. Map(); • But probably not: – Map my. Map = new Tree. Map();
Sets • We’ve talked about Sets before, and you probably remember the basic operations: – int size( ); boolean is. Empty( ); 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: Hash. Set (for when you don’t care about the order of elements) and Tree. Set (for when you do) • These are implemented by Hash. Map and Tree. Map, respectively
The End
- Slides: 28