0

I'm trying to code a spellchecker using a hashtable of dictionary words. I'm currently trying to compare words from a text document to a value in the hash table to see if it's spelled correctly, but no matter what I do, the containsValue() method always returns false even when I know it's not.

public class SpellChecker {

    private Hashtable<Integer, Wrapper> words;
    private ArrayList<Wrapper> parsedFile;

    SpellChecker() {
        words = new Hashtable<Integer, Wrapper>();
        parsedFile = new ArrayList<Wrapper>();
    }

    public void createDict(String inputFile) throws IOException {
        FileReader input = new FileReader(inputFile);
        BufferedReader bufRead = new BufferedReader(input);
        String myLine = null;
        int i = 0;
        while ((myLine = bufRead.readLine()) != null)
        {   
            Wrapper my_line = new Wrapper(myLine);
            words.put(i,my_line);
            i++;
        }
        bufRead.close();
    }

    public ArrayList<Wrapper> readFile(String inputFile) throws IOException {
        FileReader input = new FileReader(inputFile);
        BufferedReader bufRead = new BufferedReader(input);
        String myLine = null;
        Wrapper[] array_file;

        while ((myLine = bufRead.readLine()) != null)
        {   
            String[] arrayFile = myLine.split(" ");
            for (int i = 0; i < arrayFile.length; i++) {
                array_file = new Wrapper[arrayFile.length];
                arrayFile[i] = arrayFile[i].toLowerCase();

                Wrapper my_line = new Wrapper(arrayFile[i]);
                array_file[i] = my_line;
                parsedFile.add(array_file[i]);
            }
        }

        bufRead.close();
        return parsedFile;
    }

    public ArrayList<Wrapper> getParsedFile(){
        return parsedFile;
    }

    public ArrayList<String> checkMisspellings() {
        ArrayList<String> misspelled = new ArrayList<String>();

        for (int i = 0; i<parsedFile.size(); i++) {
            if (!words.containsValue(parsedFile.get(i))) {
                misspelled.add(parsedFile.get(i).backToString());
            }
        }
        return misspelled;
    }
}

I looked at some answers online that said it might be because containsValue() compares addresses, so I made a wrapper class for the String values but it still isn't working.

public class Wrapper {

    public String x;

    public Wrapper(String x){
        this.x=x;
    }

    public String backToString() {
        return x;
    }

    public boolean equals(Object o) {
   if(o == null) return false;
   if(!(o instanceof Wrapper)) return false;
   final Wrapper p = (Wrapper) o;
   if(p.x.equals(this.x)) return true;
   return false;
}

    @Override
    public int hashCode() {
      int hash = 3;
      hash = 53 * hash + x.length();
      return hash;
    }
}

the misspelled arrayList is supposed to only contain words that aren't found in the hashtable, but it always just returns all the original words. What am I doing wrong?? Here's some sample input/output:

input: hellos my name Ann corral mlks please spell correct 
output: [��hellos, my, name, ann, corral, mlks, please, spell, correct, ]

the text file I'm using for the dictionary looks something like this:

corralled
corralling
corrals
correct
correctable
corrected
correcter
correctest
correcting
Anna Li
  • 13
  • 3
  • '... it might be because containsValue() compares addresses': it isn't, and it doesn't. See the [Javadoc](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#containsValue-java.lang.Object-). – user207421 Jan 19 '19 at 07:16
  • That's what I thought but it doesn't work no matter what I try and I can't seem to figure out why :(( – Anna Li Jan 19 '19 at 07:19
  • What is the purpose of `array_file = new Wrapper[arrayFile.length];` in your loop? – Pshemo Jan 19 '19 at 07:24
  • It was to make a new array of type Wrapper so that I could compare them to the hashtable Wrapper values -- even when I didn't have the Wrapper class and worked with Strings, though, the code still didn't work so I don't think it makes a difference – Anna Li Jan 19 '19 at 07:26
  • But in each iteration you are creating a *`new Wrapper[arrayFile.length];`* in which you are setting and using only `[i]` element. This suggest it shouldn't be an array at all. – Pshemo Jan 19 '19 at 07:29
  • that's true, but I think that's a matter of space/efficiency since the result turns out the same – Anna Li Jan 19 '19 at 07:33
  • "*I looked at some answers online that said it might be because containsValue() compares addresses, so I made a wrapper class for the String values but it still isn't working.*" that shouldn't be the case, so Wrapper class shouldn't be needed. To help you with your code based on Strings we would need to see it. Also is using `Hashtable` mandatory? If not consider HashMap which usually is preferred if there is no concurrency issues. – Pshemo Jan 19 '19 at 08:27
  • Another thing we need to see is *how* you are using this code. What input you provide, when, what results you expected (why) and what you got instead? – Pshemo Jan 19 '19 at 08:32
  • With your current code I cannot reproduce your problem. I tried with `SpellChecker sp = new SpellChecker(); sp.createDict("dict.txt"); sp.readFile("input.txt"); System.out.println(sp.checkMisspellings());` and the words from dict.txt were correctly removed. – Thomas Kläger Jan 19 '19 at 08:55
  • Also `output: [��hellos,` suggests that encoding of your input file uses BOM (Byte Order Mark) character which as you see is treated as part of string. Consider changing encoding to something without BOM. – Pshemo Jan 19 '19 at 09:02

1 Answers1

2

Change p.x==this.x to p.x.equals(this.x) in your equals() method.

For more info, learn about how to compare Strings in Java.

Kartik
  • 7,677
  • 4
  • 28
  • 50
  • thanks for the answer! I tried that and it still doesn't work :( – Anna Li Jan 19 '19 at 07:05
  • @AnnaLi can you update your question with some sample input and output? perhaps you are looking for case-insensitive equality, in which case you need to use `equalsIgnoreCase()` – Kartik Jan 19 '19 at 07:08
  • I updated it! I don't think it's a matter of case since the values look exactly the same but I'll try – Anna Li Jan 19 '19 at 07:16