简体   繁体   中英

Java Hashmaps word grouping won't return more than one ArrayList

For a homework assignment I have to create a program that will cheat at hangman. In order to do this I need to come up with a way of grouping words into families via the words letter locations. So for instance if the word length is 4 and they guess "e" all words that go "- - - e " will be in one of the hashmap's Arraylists with that pattern as a key and all the words that that go "- e - -" will be in another of the same hashmap's ArrayLists with the pattern as a key. My problem is that despite my program being able to identify the pattern. It still returns an empty set or one ArrayList containing all the words. I have been trying different things for over an hour now and I can't seem to get them to group correctly. Any help is greatly appreciated. Here is the code I have for the class that separates the words and adds them to the Hashmap.

import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashMap;

public class EvilEngine 
{
HashMap<StringBuilder, ArrayList> families = new HashMap<StringBuilder, ArrayList>();
int k = 0;
ArrayList<String> currentList = new ArrayList();
StringBuilder blankPattern = new StringBuilder("");
StringBuilder newPattern = new StringBuilder("");


public void PatternMatcher(ArrayList wordlist, char guess, Integer wordlength)
{

    String word;
    int j = 0;
    int x = 0;
    int biggest = 0;
    StringBuilder longest = null;    

    while(x < wordlist.size())
    {
        int i = 0;
        int index = 0;
        for (i=0; i < wordlength; i++)
        {
            blankPattern = blankPattern.append("-");
        }
        boolean boo = false;
        newPattern = blankPattern;
        word = (String) wordlist.get(x);
        index = word.indexOf(guess);
        while (index >= 0) 
        {
            blankPattern.setCharAt(index, guess);
            newPattern = blankPattern;
            index = word.indexOf(guess, index + 1);
        }
        this.PatternCompiler(word,newPattern);
        blankPattern = blankPattern.delete(0,wordlength);
        x++;
    }
}
public void PatternCompiler (String word, StringBuilder pattern)
{
        if(!families.containsKey(pattern))
        {
            ArrayList<String> newPatternList = new ArrayList();
            newPatternList.add(word);
            families.put(pattern, newPatternList);
        }
        if (families.containsKey(pattern))
        {
            ArrayList<String> oldPatternList = new ArrayList();
            oldPatternList = families.get(pattern);
            oldPatternList.add(word);
            families.put(pattern, oldPatternList);
        }
        else {
            System.out.println("Error");
        }

}
public HashMap<StringBuilder, ArrayList> returnFamilies (){
    return families;
}
}

While there are several more-or-less minor issues with your code, I suspect the main problem is that your HashMap has keys of type StringBuilder instead of String . HashMap uses the hashCode() function of the key object to determine if it is already in the map or not. For a StringBuilder , the hash value is probably just going to be the address of the object (using the implementation inherited from the Object class).

Since newPattern is a class-level variable whose scope is outside of the functions, when you pass it to the PatternCompiler() function, the parameter pattern there is just a reference to the same class-level object (ie, will have the same hash code). And this object (nor its hash code) never changes in your code because blankPattern is also declared at the class level and, while you change the value of blankPattern , you never change the object it refers to. So re-assigning it to newPattern each time through your while loop does not change anything (and is basically clutter).

To fix that, you will want to make the key type of your HashMap be String instead of StringBuilder . The String class defines a hashCode() function that will return different codes depending on the actual contents of the string (instead of just the address of the object like StringBuilder ). (Also, as indicated, there is no reason for blankPattern to be declared at the class level instead of just inside your PatternMatcher() function, and you don't need newPattern at all.)

While that was the main issue with your code, another pretty big issue has to do with the second if condition in your PatternCompiler() function. In the previous if block you add a new ArrayList to families if there isn't already one for the pattern. So no matter what, the second if conditional ( if (families.containsKey(pattern)) ) will be true at that point. Because both blocks add word to the list for families , there is the potential that some words will be added twice.

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM