Removed/commented out/tagged some unused local variables.
Added a JUnit test for the new Trie that fails at present since the Trie is case-insensitive. Running JUnit tests is not something our build system knows about at present, but Eclipse 2.0 makes it very easy. Fixed a few compiler errors due to imports I'd forgotten.
This commit is contained in:
parent
b8391e923d
commit
a6cc4a7ff3
31 changed files with 292 additions and 179 deletions
|
@ -67,7 +67,7 @@ public class ThdlLazyExceptionTest extends TestCase {
|
|||
junit.textui.TestRunner.run(ThdlLazyExceptionTest.class);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test for void ThdlLazyException()
|
||||
*/
|
||||
public void testThdlLazyException() {
|
||||
|
@ -81,7 +81,7 @@ public class ThdlLazyExceptionTest extends TestCase {
|
|||
} /* don't catch anything else. */
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test for void ThdlLazyException(String)
|
||||
*/
|
||||
public void testThdlLazyExceptionString() {
|
||||
|
@ -91,7 +91,7 @@ public class ThdlLazyExceptionTest extends TestCase {
|
|||
assertTrue(null == e.getRealException());
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test for void ThdlLazyException(String, Throwable)
|
||||
*/
|
||||
public void testThdlLazyExceptionStringThrowable() {
|
||||
|
@ -103,7 +103,7 @@ public class ThdlLazyExceptionTest extends TestCase {
|
|||
assertTrue("bah".equals(e.getRealException().getMessage()));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test for void ThdlLazyException(Throwable)
|
||||
*/
|
||||
public void testThdlLazyExceptionThrowable() {
|
||||
|
|
|
@ -88,115 +88,161 @@ package org.thdl.util;
|
|||
public class Trie
|
||||
{
|
||||
|
||||
/** Size of the m_nextChar array. */
|
||||
public static final int ALPHA_SIZE = 128;
|
||||
/** Size of the m_nextChar array. */
|
||||
public static final int ALPHA_SIZE = 128;
|
||||
|
||||
/** The root node of the tree. */
|
||||
Node m_Root;
|
||||
|
||||
/**
|
||||
* Constructs a trie.
|
||||
*/
|
||||
public Trie()
|
||||
{
|
||||
m_Root = new Node();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an object into the trie for lookup.
|
||||
*
|
||||
* @param key must be a 7-bit ASCII string
|
||||
* @param value any java object.
|
||||
*
|
||||
* @return The old object that matched key, or null.
|
||||
*/
|
||||
public Object put(String key, Object value)
|
||||
{
|
||||
|
||||
final int len = key.length();
|
||||
Node node = m_Root;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node nextNode = node.m_nextChar[Character.toUpperCase(key.charAt(i))];
|
||||
|
||||
if (nextNode != null)
|
||||
{
|
||||
node = nextNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; i < len; i++)
|
||||
{
|
||||
Node newNode = new Node();
|
||||
|
||||
node.m_nextChar[Character.toUpperCase(key.charAt(i))] = newNode;
|
||||
node = newNode;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = node.m_Value;
|
||||
|
||||
node.m_Value = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object that matches the key.
|
||||
*
|
||||
* @param key must be a 7-bit ASCII string
|
||||
*
|
||||
* @return The object that matches the key, or null.
|
||||
*/
|
||||
public Object get(String key)
|
||||
{
|
||||
|
||||
final int len = key.length();
|
||||
Node node = m_Root;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
node = node.m_nextChar[Character.toUpperCase(key.charAt(i))];
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
||||
// the key is not 7-bit ASCII so we won't find it here
|
||||
node = null;
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return node.m_Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The node representation for the trie.
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
/** The root node of the tree. */
|
||||
Node m_Root;
|
||||
|
||||
/**
|
||||
* Constructor, creates a Node[ALPHA_SIZE].
|
||||
* Constructs a trie.
|
||||
*/
|
||||
Node()
|
||||
public Trie()
|
||||
{
|
||||
m_nextChar = new Node[ALPHA_SIZE];
|
||||
m_Value = null;
|
||||
m_Root = new Node();
|
||||
}
|
||||
|
||||
/** The next nodes. */
|
||||
Node m_nextChar[];
|
||||
/**
|
||||
* Puts an object into the trie for lookup.
|
||||
*
|
||||
* @param key must be a 7-bit ASCII string
|
||||
* @param value any java object, but not null.
|
||||
*
|
||||
* @return The old object that matched key, or null.
|
||||
* @throws NullPointerException if value is null or if key is null
|
||||
*/
|
||||
public Object put(String key, Object value)
|
||||
{
|
||||
if (null == value) throw new NullPointerException();
|
||||
|
||||
/** The value. */
|
||||
Object m_Value;
|
||||
}
|
||||
final int len = key.length();
|
||||
Node node = m_Root;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node nextNode = node.m_nextChar[Character.toUpperCase(key.charAt(i))];
|
||||
|
||||
if (nextNode != null)
|
||||
{
|
||||
node = nextNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; i < len; i++)
|
||||
{
|
||||
Node newNode = new Node();
|
||||
|
||||
node.m_nextChar[Character.toUpperCase(key.charAt(i))] = newNode;
|
||||
node.m_isLeaf = false;
|
||||
node = newNode;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = node.m_Value;
|
||||
|
||||
node.m_Value = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object that matches the key.
|
||||
*
|
||||
* @param key must be a 7-bit ASCII string
|
||||
*
|
||||
* @return The object that matches the key, or null.
|
||||
*/
|
||||
public Object get(String key)
|
||||
{
|
||||
|
||||
final int len = key.length();
|
||||
Node node = m_Root;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
node = node.m_nextChar[Character.toUpperCase(key.charAt(i))];
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
||||
// the key is not 7-bit ASCII so we won't find it here
|
||||
node = null;
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return node.m_Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if key is a prefix of another, distinct
|
||||
* member of the trie. Note that key may be in the trie as well as
|
||||
* a prefix of something in the trie, but not all keys in the trie
|
||||
* are prefixes of other keys. (In the trie you might naturally
|
||||
* construct for the extended Wylie keyboard, "t" is a prefix, as is
|
||||
* "ts", but "tsh", though a member of the trie, is not a prefix
|
||||
* because there is no string x such that x begins with "tsh" but is
|
||||
* not equal to "tsh" that is in the trie.)
|
||||
*
|
||||
* @param key must be a 7-bit ASCII string
|
||||
*
|
||||
* @return The object that matches the key, or null. */
|
||||
public boolean hasPrefix(String key)
|
||||
{
|
||||
|
||||
final int len = key.length();
|
||||
Node node = m_Root;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
node = node.m_nextChar[Character.toUpperCase(key.charAt(i))];
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
||||
// the key is not 7-bit ASCII so we won't find it here
|
||||
node = null;
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
return !node.m_isLeaf;
|
||||
}
|
||||
|
||||
/**
|
||||
* The node representation for the trie.
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor, creates a Node[ALPHA_SIZE].
|
||||
*/
|
||||
Node()
|
||||
{
|
||||
m_nextChar = new Node[ALPHA_SIZE];
|
||||
m_Value = null;
|
||||
m_isLeaf = true;
|
||||
}
|
||||
|
||||
/** The next nodes. */
|
||||
Node m_nextChar[];
|
||||
|
||||
/** The value. */
|
||||
Object m_Value;
|
||||
|
||||
/** True if and only if this node has no children. */
|
||||
boolean m_isLeaf;
|
||||
}
|
||||
}
|
||||
|
|
81
source/org/thdl/util/TrieTest.java
Normal file
81
source/org/thdl/util/TrieTest.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
package org.thdl.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author David Chandler
|
||||
*
|
||||
* Tests {@link org.thdl.util.Trie} at the unit level.
|
||||
*/
|
||||
public class TrieTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Constructor for TrieTest.
|
||||
* @param arg0
|
||||
*/
|
||||
public TrieTest(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(TrieTest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the trie distinguishes between uppercase and
|
||||
* lowercase. */
|
||||
public void testCaseSupport() {
|
||||
Trie t = new Trie();
|
||||
t.put("S", "S value");
|
||||
assertTrue(t.get("S").equals("S value"));
|
||||
assertTrue(null == t.get("s"));
|
||||
t.put("Sh", "Sh value");
|
||||
assertTrue(t.get("Sh").equals("Sh value"));
|
||||
assertTrue(t.get("S").equals("S value"));
|
||||
assertTrue(null == t.get("s"));
|
||||
assertTrue(null == t.get("sh"));
|
||||
assertTrue(null == t.get("SH"));
|
||||
assertTrue(null == t.get("sH"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for put(String, Object)
|
||||
*/
|
||||
public void testReplacement() {
|
||||
Trie t = new Trie();
|
||||
t.put("S", "S value 1");
|
||||
assertTrue(t.get("S").equals("S value 1"));
|
||||
t.put("S", "S value 2");
|
||||
assertTrue(t.get("S").equals("S value 2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that put(*, null) throws a NullPointerException.
|
||||
*/
|
||||
public void testPuttingNull() {
|
||||
Trie t = new Trie();
|
||||
boolean threw = false;
|
||||
try {
|
||||
t.put("heya", null);
|
||||
} catch (NullPointerException e) {
|
||||
threw = true;
|
||||
}
|
||||
assertTrue(threw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for put(String, Object)
|
||||
*/
|
||||
public void testPrefix() {
|
||||
Trie t = new Trie();
|
||||
t.put("t", "t value");
|
||||
t.put("ts", "ts value");
|
||||
t.put("tsh", "tsh value");
|
||||
assertTrue(t.get("t").equals("t value"));
|
||||
assertTrue(t.get("ts").equals("ts value"));
|
||||
assertTrue(t.get("tsh").equals("tsh value"));
|
||||
assertTrue(t.hasPrefix("t"));
|
||||
assertTrue(t.hasPrefix("ts"));
|
||||
assertTrue(!t.hasPrefix("tsh"));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue