2013-04-25 31 views
0

對於作業分配,我必須創建一個程序,將欺騙hang子手。爲了做到這一點,我需要想出一種通過字母位置將單詞分組到家庭的方法。因此,舉例來說,如果單詞長度是4,並且他們猜測「e」,那麼所有會出現「 - - - e」的單詞都會出現在hashmap的Arraylist中,其中一個模式作爲關鍵字, - 「將會在另一個相同的hashmap的ArrayLists中以模式作爲關鍵字。我的問題是,儘管我的程序能夠識別模式。它仍然返回一個空集或一個包含所有單詞的ArrayList。現在我一直在嘗試不同的事情一個多小時,我似乎無法讓他們正確分組。任何幫助是極大的讚賞。這裏是我爲類分離單詞並將其添加到Hashmap的代碼。Java Hashmaps單詞分組不會返回多個ArrayList

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; 
} 
} 
+0

「wordlist」中的每個單詞是否保證長度爲「wordlength」?你應該跳過長度不正確的單詞。 – 2013-04-25 01:51:23

+0

是的,我已經將字典文件剪切成只包含適當長度單詞的ArrayList。出於某種原因,它不斷返回一張空白的地圖。 – 2013-04-25 02:00:58

回答

0

雖然有與您的代碼幾個或多或少的小問題,我懷疑的主要問題是,你的HashMapStringBuilder,而不是String類型的鑰匙。 HashMap使用鍵對象的hashCode()函數來確定它是否已經在地圖中。對於StringBuilder,散列值可能只是該對象的地址(使用從Object類繼承的實現)。

由於newPattern是一個類級變量,其範圍是的功能外,當你把它傳遞給PatternCompiler()功能,參數pattern存在的僅僅是參考相同類級對象(即,將具有相同的散列碼)。並且此對象(或其哈希代碼)在您的代碼中永遠不會更改,因爲blankPattern也在類級別聲明,並且在更改的值blankPattern時,絕不會更改它引用的對象。因此,每次通過while循環將其重新分配給newPattern不會改變任何內容(並且基本上是混亂的)。

要解決該問題,您需要將HashMap的密鑰類型設置爲String而不是StringBuilderString類定義了一個hashCode()函數,該函數將根據字符串的實際內容(而不僅僅是像StringBuilder之類的對象的地址)返回不同的代碼。 (同時,隨着指出,沒有理由爲blankPattern在類的層次上,而不是隻有PatternMatcher()函數內部聲明,並且你不需要newPattern在所有。)

雖然這是與主要問題您代碼,另一個相當大的問題與PatternCompiler()函數中的第二個if條件有關。在之前的if塊中,如果模式中沒有一個,則向系列添加新的ArrayList。所以無論如何,第二個if有條件(if (families.containsKey(pattern)))將在這一點上是真實的。因爲這兩個塊將word添加到families的列表中,所以有可能會將一些單詞添加兩次。

祝你好運!

+0

'StringBuilder'未被記錄爲實現'hashCode',因此它將使用'Object'的默認實現。*但請不要稱之爲「對象的地址」,因爲這是誤導性的,通常甚至是錯誤的。另外,我還會補充說,使用可變對象作爲「Map」的關鍵字是一種固有的危險操作(偏好'String'的另一個原因)。 – 2013-04-25 06:29:49

+0

@Joachim_Saur關於可變鍵的好處。我想我的「可能」w.r.t.t.上面的地址太強大了。由於從來沒有真正看過它是如何實現的,所以我對「典型」這個詞感到好奇,因爲它在上面鏈接到的Object的hashCode()文檔的最後一段落中,相對於「通常是錯誤的」。這是什麼正常執行? (並非試圖發起爭議 - 我真的很好奇。) – Turix 2013-04-25 08:30:34

+0

AFAIK OpenJDK(和Sun JDK)計算一些初始地址的散列並將其存儲在對象頭中。源代碼中有其他實現(包括使用隨機函數的實現),但是它們通過編譯時開關禁用。不是單獨地址的一個主要原因是當垃圾收集器移動對象時,地址可以很容易地改變。 – 2013-04-25 09:34:55