Implementing LinkedMap
Here is the Map interface:
public interface Map<K, V> {
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
}
Every method that takes a key throws an IllegalArgumentException if the key is null. put also throws it if the value is null.
LinkedMap<K, V> implements the Map<K, V> interface 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;
}
}
public LinkedMap() {
head = null;
size = 0;
}
@Override
public int size() {
return size;
}
// the other operations go here
}
Solution
@Override
public V get(K key) {
if (key == null) {
throw new IllegalArgumentException();
}
Node<K, V> curr = head;
while (curr != null) {
if (key.equals(curr.key)) {
return curr.value;
}
curr = curr.next;
}
return null;
}
Solution
@Override
public boolean put(K key, V value) {
if (key == null || value == null) {
throw new IllegalArgumentException();
}
Node<K, V> curr = head;
while (curr != null) {
if (key.equals(curr.key)) {
curr.value = value;
return false;
}
curr = curr.next;
}
Node<K, V> newNode = new Node<>(key, value);
newNode.next = head;
head = newNode;
size++;
return true;
}
Solution
@Override
public boolean remove(K key) {
if (key == null) {
throw new IllegalArgumentException();
}
Node<K, V> prev = null;
Node<K, V> curr = head;
while (curr != null) {
if (key.equals(curr.key)) {
if (prev != null) {
prev.next = curr.next;
} else {
head = head.next;
}
size--;
return true;
}
prev = curr;
curr = curr.next;
}
return false;
}
Solution
size is : it returns a field. get and containsKey are : each is a linear search for the key. put is : replacing a value or inserting at the head is , but the search for the key comes first. remove is : the unlink is , but finding the node is a linear search.