001/** 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on 5 Mar 2013 021 * Created by Andreas Prlic 022 * 023 * @since 3.0.6 024 */ 025package org.biojava.nbio.structure.math; 026 027 028import java.io.Serializable; 029import java.util.Iterator; 030import java.util.SortedMap; 031import java.util.TreeMap; 032 033/** 034 * Sorted symbol table implementation using a java.util.TreeMap. 035 * Does not allow duplicate keys. 036 * 037 * This class represents an ordered symbol table. It assumes that 038 * the elements are <tt>Comparable</tt>. 039 * It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>, 040 * and <em>delete</em> methods. 041 * It also provides ordered methods for finding the <em>minimum</em>, 042 * <em>maximum</em>, <em>floor</em>, and <em>ceiling</em>. 043 * <p> 044 * The class uses the convention that values cannot be null. Setting the 045 * value associated with a key to null is equivalent to removing the key. 046 * <p> 047 * This implementation uses a balanced binary search tree. 048 * The <em>add</em>, <em>contains</em>, <em>delete</em>, <em>minimum</em>, 049 * <em>maximum</em>, <em>ceiling</em>, and <em>floor</em> methods take 050 * logarithmic time. 051 * 052 * Derived from http://introcs.cs.princeton.edu/java/44st/ST.java.html 053 * 054 * <p> 055 * For additional documentation, see <a href="http://introcs.cs.princeton.edu/44st">Section 4.4</a> of 056 * <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne. 057 * 058 */ 059public class SymbolTable<Key extends Comparable<Key>, Value> implements Iterable<Key>, Serializable { 060 061 /** 062 * 063 */ 064 private static final long serialVersionUID = -4417561575046471931L; 065 066 private TreeMap<Key, Value> st; 067 068 /** 069 * Create an empty symbol table. 070 */ 071 public SymbolTable() { 072 st = new TreeMap<Key, Value>(); 073 } 074 075 /** 076 * Put key-value pair into the symbol table. Remove key from table if 077 * value is null. 078 */ 079 public void put(Key key, Value val) { 080 if (val == null) st.remove(key); 081 else st.put(key, val); 082 } 083 084 /** 085 * Return the value paired with given key; null if key is not in table. 086 */ 087 public Value get(Key key) { 088 return st.get(key); 089 } 090 091 /** 092 * Delete the key (and paired value) from table. 093 * Return the value paired with given key; null if key is not in table. 094 */ 095 public Value delete(Key key) { 096 return st.remove(key); 097 } 098 099 /** 100 * Is the key in the table? 101 */ 102 public boolean contains(Key key) { 103 return st.containsKey(key); 104 } 105 106 /** 107 * How many keys are in the table? 108 */ 109 public int size() { 110 return st.size(); 111 } 112 113 /** 114 * Return an <tt>Iterator</tt> for the keys in the table. 115 * To iterate over all of the keys in the symbol table <tt>st</tt>, use the 116 * foreach notation: <tt>for (Key key : st)</tt>. 117 */ 118 @Override 119 public Iterator<Key> iterator() { 120 return st.keySet().iterator(); 121 } 122 123 /** 124 * Return an <tt>Iterable</tt> for the keys in the table. 125 * To iterate over all of the keys in the symbol table <tt>st</tt>, use the 126 * foreach notation: <tt>for (Key key : st.keys())</tt>. 127 */ 128 public Iterable<Key> keys() { 129 return st.keySet(); 130 } 131 132 /** 133 * Return the smallest key in the table. 134 */ 135 public Key min() { 136 return st.firstKey(); 137 } 138 139 /** 140 * Return the largest key in the table. 141 */ 142 public Key max() { 143 return st.lastKey(); 144 } 145 146 /** 147 * Return the smallest key in the table >= k. 148 */ 149 public Key ceil(Key k) { 150 SortedMap<Key, Value> tail = st.tailMap(k); 151 if (tail.isEmpty()) return null; 152 else return tail.firstKey(); 153 } 154 155 /** 156 * Return the largest key in the table <= k. 157 */ 158 public Key floor(Key k) { 159 if (st.containsKey(k)) return k; 160 161 // does not include key if present (!) 162 SortedMap<Key, Value> head = st.headMap(k); 163 if (head.isEmpty()) return null; 164 else return head.lastKey(); 165 } 166 167}