Implementing entries()
Here is the Map interface. A map is iterable over its keys, and entries() returns a separate Iterable over its key–value pairs. Each pair is handed back as a Map.Entry:
public interface Map<K, V> extends Iterable<K> {
boolean put(K key, V value); // stores value under key, replacing any old value;
// returns true if the key was not present before
V get(K key); // returns the value stored under key, or null if key is absent
boolean remove(K key); // removes key and its value if key is present;
// returns true if the map changed
boolean containsKey(K key); // returns true if key is in the map
int size(); // returns the number of key-value pairs in the map
Iterable<Map.Entry<K, V>> entries(); // returns an Iterable over the key-value pairs
interface Entry<K, V> {
K key(); // returns the key of this pair
V value(); // returns the value of this pair
}
}
Here is the Iterator<T> interface:
public interface Iterator<T> {
boolean hasNext(); // returns true if there are items left to return; does not advance
T next(); // returns the next item and advances past it;
// throws NoSuchElementException if there are no items left
}
LinkedMap<K, V> implements Map<K, V> with a singly linked list, one node per pair:
public class LinkedMap<K, V> implements Map<K, V> {
private Node<K, V> head; // the first node, or null when empty
private int size; // how many pairs the map holds
private static class Node<K, V> {
K key;
V value;
Node<K, V> next;
Node(K key, V value) {
this.key = key;
this.value = value;
}
}
// the Map operations and the key iterator are already implemented
@Override
public Iterable<Map.Entry<K, V>> entries() {
return null; // TODO
}
}
Solution
Node implements Map.Entry<K, V>:
private static class Node<K, V> implements Map.Entry<K, V> {
K key;
V value;
Node<K, V> next;
Node(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K key() {
return key;
}
@Override
public V value() {
return value;
}
}
entries() returns an Entries object. Entries is an Iterable whose iterator() creates an EntryIterator:
@Override
public Iterable<Map.Entry<K, V>> entries() {
return new Entries();
}
private class Entries implements Iterable<Map.Entry<K, V>> {
@Override
public Iterator<Map.Entry<K, V>> iterator() {
return new EntryIterator();
}
}
private class EntryIterator implements Iterator<Map.Entry<K, V>> {
private Node<K, V> current = head; // node that comes next
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Map.Entry<K, V> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node<K, V> node = current;
current = current.next;
return node;
}
}
Solution
The caller receives each node as a Map.Entry<K, V>, which has only key() and value(). Node is a private class of LinkedMap, so code outside the map cannot name it, cast to it, or reach its fields.
Solution
The traversal is : it makes calls to next(), and each is . The auxiliary space is : the iterator holds one node reference and hands back nodes that already exist, so it copies nothing.