I have written the following program and its test. When I run it on eclipse I get a NullPointerException. I don’t know how to fix.
What the program does:
It’s a data structure with two methods: addWord(word)
and search(word)
. search(word)
can search a literal word or a regular expression string containing only letters a-z
or .
. A .
means it can represent any one letter.
For example:
addWord("bad")
addWord("dad")
addWord("mad")
search("pad") -> false
search("bad") -> true
search(".ad") -> true
search("b..") -> true
Now before I show you my code, let me show the test case and point to what causes the NPE to happen.
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class WordDictionaryText {
@Test
public void test() {
WordDictionary dict = new WordDictionary();
List<Boolean> result = new ArrayList<>();
dict.addWord("ran");
dict.addWord("rune");
dict.addWord("runner");
dict.addWord("runs");
dict.addWord("add");
dict.addWord("adds");
dict.addWord("adder");
dict.addWord("addee");
result.add(dict.search("r.n"));
result.add(dict.search("ru.n.e"));
result.add(dict.search("add"));
result.add(dict.search("add."));
result.add(dict.search("adde."));
result.add(dict.search(".an.”));//NPE caused by this line: i.e. by searching for string “.an.”
result.add(dict.search("...s"));
result.add(dict.search("....e."));
result.add(dict.search("......."));
result.add(dict.search("..n.r"));
System.out.println(result);
}
}
So the NPE is caused by the line dict.search(".an.”)
.
Here is the complete code.
import java.util.HashMap;
import java.util.Map;
public class WordDictionary {
Trie trie;
public WordDictionary() {
trie = new Trie();
}
// Adds a word into the data structure.
public void addWord(String word) {
trie.addWord(word);
}
// Returns if the word is in the data structure. A word could
// contain the dot character '.' to represent any one letter.
public boolean search(String word) {
if (null != word && !word.isEmpty()) {
return trie.findWord(word);
}
return false;
}
}
// /////////////////////////////
class Trie {
TrieNode root;
public Trie() {
root = new TrieNode((char) 0);
}
public void addWord(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
TrieNode next = node.getNext(c);
if (null == next) {
next = new TrieNode(c);
node.addNext(c, next);
}
node = next;
}
node.isWord = true;
}
boolean findWord(String word) {
TrieNode nextNode = root;
for (int i = 0; i < word.length(); i++) {
char curr = word.charAt(i);
if ('.' != curr) {
nextNode = nextNode.getNext(curr);
if (null == nextNode) {
return false;
}
} else {
java.util.Collection<TrieNode> collection = nextNode.getNextList();
if (!collection.isEmpty()) {
for (TrieNode tmp : nextNode.getNextList()) {
if (findWord(word, tmp)) {
return true;
}
}
}
return false;
}
}
return nextNode.isWord;
}
boolean findWord(String word, TrieNode nextNode) {
for (int i = 0; i < word.length(); i++) {
char curr = word.charAt(i);
if ('.' == curr) {
java.util.Collection<TrieNode> collection = nextNode.getNextList();
if (i + 1 < word.length() && !collection.isEmpty()) {
for (TrieNode tmp : collection) {
if (null != tmp && findWord(word.substring(i + 1), tmp)) {
return true;
}
}
return false;
} else {
return nextNode.isWord;
}
} else if (curr != nextNode.val) {
return false;
}
if (i + 1 < word.length()) {
nextNode = nextNode.getNext(word.charAt(i + 1));
}
}
return nextNode.isWord;
}
}
// /////////////////////////////
class TrieNode {
char val;
Map<Character, TrieNode> next;
boolean isWord;
public TrieNode(char val) {
this.val = val;
next = new HashMap<>();
}
public TrieNode getNext(char c) {
return next.get(c);
}
public void addNext(char c, TrieNode node) {
next.put(c, node);
}
public java.util.Collection<TrieNode> getNextList() {
return next.values();
}
}
Feel free to copy and paste into eclipse both the code and the test. Thanks for any help.
In case you cannot run the program on Eclipse, here is the error
java.lang.NullPointerException
at algo.Trie.findWord(WordDictionary.java:80)
at algo.Trie.findWord(WordDictionary.java:83)
at algo.Trie.findWord(WordDictionary.java:64)
at algo.WordDictionary.search(WordDictionary.java:23)
at test.WordDictionaryText.test(WordDictionaryText.java:29)
The error corresponds to
line 80: java.util.Collection<TrieNode> collection = nextNode.getNextList();
line 83: if (null != tmp && findWord(word.substring(i + 1), tmp))
line 64: if (findWord(word, tmp))
line 23: return trie.findWord(word);
UPDATE: The question was erroneously closed to answers but I have the answer: findWord() has both a recursive and an iterative advancement of the nextNode value. The iterative advancement is what sets the value to null.
Put a breakpoint in findWord() on the line: nextNode = nextNode.getNext(word.charAt(i + 1));