title: Java: I can't for the life of me figure out why I'm getting a NullPointerException here
body: <p>I'm creating a console-based Evil Hangman program. Instead of selecting a word at the beginning of the game, a list of words is progressively narrowed down by selecting out words that contain letters that the user inputs.</p>
  
  <p>This is a pretty common assignment, so I'm sure that you've heard of something similar before. </p>
  
  <p>Here is the specification, in case if you need more clarification.</p>
  
  <p><a href="http://courses.cs.washington.edu/courses/cse143/15wi/homework/5/spec.pdf" rel="nofollow">Specification</a></p>
  
  <p>Necessary file and client for compilation:</p>
  
  <p><a href="http://courses.cs.washington.edu/courses/cse143/15wi/homework/5/dictionary.txt" rel="nofollow">File</a></p>
  
  <p><a href="http://courses.cs.washington.edu/courses/cse143/15wi/homework/5/HangmanMain.java" rel="nofollow">HangmanMain</a></p>
  
  <p>The problematic method in this particular class is the record() method, which is by far the most difficult method to program in this assignment.
  There are two main problems that I'm observing:</p>
  
  <p>a) There is the following NullPointerException that I can't figure out the reason for. It's occurring at a line where a word is being added to the list. As far as I can tell, the word and the list should both exist and are both initialized. It's not a matter of the list not containing a word or of the list not being properly initialized. It seems to only happen after the second user input.</p>
  
  <pre><code>Exception in thread "main" java.lang.NullPointerException
  at HangmanManager.record(HangmanManager.java:66)
  at HangmanMain.playGame(HangmanMain.java:59)
  at HangmanMain.main(HangmanMain.java:39)
  </code></pre>
  
  <p>b) The NullPointerException is probably caused at my earlier attempts to fix another problem. Before the NullPointerException occurred, I was experiencing problems determining why the word selected by the program wasn't following the expected output. No matter what I did, the word selected by the program at the end of the traversal would always be "aa." Even when I had deliberately chose 'a' as a guess, which should have effectively filtered out "aa" as a choice, it still showed up.</p>
  
  <p>Here is my program so far.</p>
  
  <pre><code>import java.util.*;
  public class HangmanManager {
  private String pattern;
  private int length;
  private int max;
  private SortedSet&lt;Character&gt; guessesMade;
  private Set&lt;String&gt; words;
  private Set&lt;String&gt; currentWords;
  private Map&lt;String, Set&lt;String&gt;&gt; patternMap;
  
  public HangmanManager(List&lt;String&gt; dictionary, int length, int max){
      if (length &lt; 1 || max &lt; 0){
          throw new IllegalArgumentException();
      }
      this.length = length;
      this.max = max;
      words = new TreeSet&lt;String&gt;();
      for (String word : dictionary){
          if (word.length() == length){
              words.add(word);
          }
      }
      currentWords = new TreeSet&lt;String&gt;();
      guessesMade = new TreeSet&lt;Character&gt;();
      patternMap = new TreeMap&lt;String, Set&lt;String&gt;&gt;();
      pattern = "";
      for (int i = 0; i &lt; length; i++){
          pattern += "- ";
      }
  
  }
  public Set&lt;String&gt; words(){
      return words;
  }
  public int guessesLeft(){
      return max - guessesMade.size();
  }
  public SortedSet&lt;Character&gt; guesses(){
      return guessesMade;
  }
  public String pattern(){
      if (words.isEmpty()){
          throw new IllegalArgumentException("There are no words.");
      }
      return pattern;
  }
  
  public int record(char guess){
      if (guessesLeft() &lt; 1 || words.isEmpty()){
          throw new IllegalStateException();  
      }
      if (!words.isEmpty() &amp;&amp; guessesMade.contains(guess)) { 
          throw new IllegalArgumentException();
      }
      guessesMade.add(guess);
      int largestOccurences = 0;
      for (String word: words){
          System.out.println(word);
          System.out.println(words.size());
          if (patternMap.containsKey(pattern)){   
              System.out.println("patternMap contains pattern");
              largestOccurences = generatePattern(word, guess);
              currentWords.add(word);
              currentWords = patternMap.get(pattern);
              patternMap.put(pattern, currentWords);          
          } else {
              currentWords.add(word);
              patternMap.put(pattern, currentWords);
          }
      }
      words = findFamily();
      return largestOccurences;
  }
  private Set&lt;String&gt; findFamily(){
      int maxSize = 0;
      Map &lt;String, Integer&gt; patternCount = new TreeMap&lt;String, Integer&gt;();
      for (String key : patternMap.keySet()){
          patternCount.put(key, patternMap.get(key).size());
              if (patternMap.get(key).size() &gt; maxSize){
                  maxSize = patternMap.get(key).size();
                  pattern = key;
              } else if (patternMap.get(key).size() == maxSize){
                  if (key.length() &gt;= pattern.length()){
                      pattern = key;
                      maxSize = patternMap.get(key).size();
                  }
              }
          }
      System.out.println("Current pattern: " + pattern);
      return patternMap.get(pattern);
  }
  
  private int generatePattern(String s, char guess) {
      int count = 0;
      pattern = "";
          for (int i = 0; i &lt; length; i++){
              if (s.charAt(i) == guess){
                  pattern += guess + " ";
                  count++;
              } else {
                  pattern += "- ";
              }
          }
      return count;
  }
  }
  </code></pre>