package com.jwetherell.algorithms.data_structures; import com.jwetherell.algorithms.data_structures.SkipList.Node; import com.jwetherell.algorithms.data_structures.interfaces.IMap; /** * A set used to store key->values pairs, this is an implementation of an * associative array. * * This implementation is a composition of a Skip List as the backing structure. * * http://en.wikipedia.org/wiki/Skip_list * http://en.wikipedia.org/wiki/Associative_array * * @author Justin Wetherell */ @SuppressWarnings("unchecked") public class SkipListMap, V> implements SkipList.INodeCreator, IMap { private SkipList list = null; public SkipListMap() { list = new SkipList(this); } /** * {@inheritDoc} */ @Override public V put(K key, V value) { V prev = null; SkipList.Node node = list.addValue(key); if (node instanceof SkipListMapNode) { SkipListMapNode treeMapNode = (SkipListMapNode) node; if (treeMapNode.value!=null) prev = treeMapNode.value; treeMapNode.value = value; } return prev; } /** * {@inheritDoc} */ @Override public V get(K key) { SkipList.Node node = list.getNode(key); if (node instanceof SkipListMapNode) { SkipListMapNode mapNode = (SkipListMapNode) node; return mapNode.value; } return null; } /** * {@inheritDoc} */ @Override public boolean contains(K key) { return list.contains(key); } /** * {@inheritDoc} */ @Override public V remove(K key) { Node node = list.removeValue(key); V value = null; if (node instanceof SkipListMapNode) { SkipListMapNode treeMapNode = (SkipListMapNode) node; value = treeMapNode.value; treeMapNode.data = null; treeMapNode.value = null; } return value; } /** * {@inheritDoc} */ @Override public void clear() { list.clear(); } /** * {@inheritDoc} */ @Override public int size() { return list.size(); } /** * {@inheritDoc} */ @Override public boolean validate() { if (list==null) return true; java.util.Set keys = new java.util.HashSet(); Node node = list.head; if (node==null) return true; if (!validate(node,keys)) return false; Node next = node.getNext(0); while (next!=null) { if (!validate(next, keys)) return false; next = next.getNext(0); } return (keys.size()==size()); } private boolean validate(Node node, java.util.Set keys) { if (!(node instanceof SkipListMapNode)) return false; SkipListMapNode tmn = (SkipListMapNode)node; K k = tmn.data; V v = tmn.value; if (k==null || v==null) return false; if (keys.contains(k)) return false; keys.add(k); return true; } /** * {@inheritDoc} */ @Override public java.util.Map toMap() { return (new JavaCompatibleTreeMap(this)); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(); if (list!=null && list.head!=null) { Node node = list.head; while (node!=null) { if (!(node instanceof SkipListMapNode)) continue; SkipListMapNode sln = (SkipListMapNode) node; builder.append(sln.data).append("=").append(sln.value); node = node.getNext(0); if (node!=null) builder.append("\n"); } } return builder.toString(); } /** * {@inheritDoc} */ @Override public SkipList.Node createNewNode(int level, K key) { return (new SkipListMapNode(level, key)); } /** * {@inheritDoc} */ @Override public void swapNode(Node node, Node next) { K key = node.data; node.data = next.data; next.data = key; if (node instanceof SkipListMapNode && next instanceof SkipListMapNode) { SkipListMapNode node2 = (SkipListMapNode) node; SkipListMapNode next2 = (SkipListMapNode) next; V value = node2.value; node2.value = next2.value; next2.value = value; } } protected static class SkipListMapNode, V> extends SkipList.Node { protected V value = null; protected SkipListMapNode(int level, K key) { super(level, key); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(super.toString()); builder.append("value = ").append(value).append("\n"); return builder.toString(); } } private static class JavaCompatibleIteratorWrapper,V> implements java.util.Iterator> { private SkipListMap map = null; private java.util.Iterator> iter = null; private java.util.Map.Entry lastEntry = null; public JavaCompatibleIteratorWrapper(SkipListMap map, java.util.Iterator> iter) { this.map = map; this.iter = iter; } /** * {@inheritDoc} */ @Override public boolean hasNext() { if (iter==null) return false; return iter.hasNext(); } /** * {@inheritDoc} */ @Override public java.util.Map.Entry next() { if (iter==null) return null; lastEntry = iter.next(); return lastEntry; } /** * {@inheritDoc} */ @Override public void remove() { if (iter==null || lastEntry==null) return; map.remove(lastEntry.getKey()); iter.remove(); } } private static class JavaCompatibleMapEntry,V> extends java.util.AbstractMap.SimpleEntry { private static final long serialVersionUID = 3282082818647198608L; public JavaCompatibleMapEntry(K key, V value) { super(key, value); } } private static class JavaCompatibleTreeMap,V> extends java.util.AbstractMap { private SkipListMap map = null; protected JavaCompatibleTreeMap(SkipListMap map) { this.map = map; } /** * {@inheritDoc} */ @Override public V put(K key, V value) { return map.put(key, value); } /** * {@inheritDoc} */ @Override public V remove(Object key) { return map.remove((K)key); } /** * {@inheritDoc} */ @Override public void clear() { map.clear(); } /** * {@inheritDoc} */ @Override public boolean containsKey(Object key) { return map.contains((K)key); } /** * {@inheritDoc} */ @Override public int size() { return map.size(); } /** * {@inheritDoc} */ @Override public java.util.Set> entrySet() { java.util.Set> set = new java.util.HashSet>() { private static final long serialVersionUID = 1L; /** * {@inheritDoc} */ @Override public java.util.Iterator> iterator() { return (new JavaCompatibleIteratorWrapper(map,super.iterator())); } }; if (map.list!=null && map.list.head!=null) { Node n = map.list.head; while (n!=null) { if (!(n instanceof SkipListMapNode)) continue; SkipListMapNode node = (SkipListMapNode)n; set.add(new JavaCompatibleMapEntry(node.data,node.value)); n = node.getNext(0); } } return set; } } }