簡體   English   中英

通過Hashtable迭代的無限循環

[英]Infinite Loop Iterating Through Hashtable

我正在嘗試使用Hashtables在數組中找到最流行的單詞。 由於某種原因,while循環無限循環。 我已經調試了,元素永遠不會從它得到的第一個變化。 有關為什么會發生這種情況的任何想法?

這是我的代碼:

import java.util.Hashtable;

public class MyClass {
  public String mostPopularString (String []words) {
    if (words == null)
            return null;
    if (words.length == 0)
            return null;
    Hashtable<String, Integer> wordsHash = new Hashtable<String, Integer>();
    for (String thisWord : words)
    {
        if (wordsHash.containsKey(thisWord))
        {
            wordsHash.put(thisWord, wordsHash.get(thisWord) + 1);
        }
        else
        {
            wordsHash.put(thisWord, 1);
        }
    }
    Integer mostPopularCount = 0;
    String mostPopularWord = null;
    boolean tie = false;
    while (wordsHash.keys().hasMoreElements())
    {
        String currentWord = (String) wordsHash.keys().nextElement();
        if (wordsHash.get(currentWord) > mostPopularCount)
        {
            mostPopularCount = wordsHash.get(currentWord);
            mostPopularWord = currentWord;
            tie = false;
        }
        else if (wordsHash.get(currentWord) == mostPopularCount)
        {
            tie = true;
        }
    }
    if (tie)
        return null;
    else
        return mostPopularWord;
  }
}

你在循環的每次迭代中調用wordsHash.keys() ,這會在每次迭代時給你一個新的Enumeration<String> - 然后你在循環再次調用它。

您想要調用一次 ,然后遍歷單個Enumeration<String>

Enumeration<String> iterator = wordsHash.keys();
while (iterator.hasMoreElements())
{
    String currentWord = iterator.nextElement();
    ...
}

請注意,因為您還獲得了每個元素的值,所以最好迭代entrySet()而不是keys()

你最好還是使用HashMap而不是Hashtable ,因為你可以使用增強的for循環......

問題是符合的

while (wordsHash.keys().hasMoreElements())

每次循環時,您都會獲得枚舉的新副本。 您將需要獲取一次密鑰集,並對其進行迭代。

在這里使用增強的for循環可能更容易

   for (Map.Entry<String,Integer> entry : wordsHash.entrySet()) {
        String currentWord = entry.getKey();
        Integer currentCount = entry.getValue();
        //more code here
    }

這應該提供您想要的行為,同時更簡單,更容易閱讀。

問題是無論何時調用wordsHash.keys() ,它都會返回一個新的枚舉:

while (wordsHash.keys().hasMoreElements())                        // <=== HERE
{
    String currentWord = (String) wordsHash.keys().nextElement(); // <=== AND HERE

您需要做的是創建一個枚舉並在整個循環中使用它。

PS你為什么使用Hashtable而不是HashMap

每次調用.keys()返回一個新的枚舉,並帶有一個用於迭代的新內部指針:

Hashtable table = new Hashtable();
table.put("a", "a");
table.put("b", "b");
boolean b = table.keys() == table.keys();
System.out.println(b); // false
                       // the two calls to `.keys()` returned different instances of Enumeration

因此,將keys枚舉分配給變量:

Enumeration keys = wordsHash.keys();
while (keys.hasMoreElements())
{
    String currentWord = (String) keys.nextElement();

}

將您的代碼更改為:

Enumeration<String> keys = wordsHash.keys();
while (keys.hasMoreElements()) {
    String currentWord = keys.nextElement();

因此,每次進入循環時都不會創建指向HashTable的第一個鍵的新枚舉。

什么都沒有修改wordsHash 這意味着如果wordsHash.keys().hasMoreElements()為真一次,則對於程序的其余部分,它將繼續為真。 這會導致無限循環。 您需要在進行時刪除密鑰,或者只需使用for

你得到一個新的Iterable ofer每個循環迭代的所有鍵: wordsHash.keys()只要其中至少有一個鍵,while循環永遠不會結束。

更換:

while (wordsHash.keys().hasMoreElements()){
   String currentWord = (String) wordsHash.keys().nextElement();

通過

for (String currentWord: wordsHash.keys()){

此外,與您的枚舉問題無關,這可能是一個缺陷:

else if (wordsHash.get(currentWord) == mostPopularCount)

這是java.lang.Integer與另一個java.lang.Integer的參考比較。 它不是它們所代表的實際值的比較。 它適用於“小”數字,因為自動裝箱使用緩存的引用,但最終會破壞。 你可能想要:

else if (wordsHash.get(currentWord) == mostPopularCount.intValue())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM