0

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));

aro_tech
  • 1,103
  • 7
  • 20
Katedral Pillon
  • 14,534
  • 25
  • 99
  • 199
  • nextNode seems to be null, verify this by using a conditional breakpoint at line 80, using (nextNode == null) as a condition – Fabinout Jul 15 '15 at 15:18
  • I already did that. I still can't figure out how to fix it. – Katedral Pillon Jul 15 '15 at 15:27
  • I already saw the link that this is supposed to be duplicate of. It does not help at all. I you look at my problem you will see that I am filling nextNode from a collection (line 83) so that null should not be possible. Please run the code if you can. Thanks. – Katedral Pillon Jul 15 '15 at 15:33
  • I notice that the closing `"` is stylized (`”`) for the one string that gives you a problem – clcto Jul 15 '15 at 15:48
  • @clcto that is due to copying into text editor. It's not a problem in the code itself: eclipse would have caught it at compile time. Still I double checked. It's not the problem. Thanks. – Katedral Pillon Jul 15 '15 at 16:20
  • 1
    @KatedralPillon Hello at line 93 " nextNode = nextNode.getNext(word.charAt(i + 1)); " you sometimes set it to null before looping – Fabinout Jul 15 '15 at 17:12
  • @KatedralPillon can you update your post with your functional code? – Fabinout Jul 16 '15 at 07:43

0 Answers0