通过Hashtable迭代的无限循环

时间:2013-01-30 19:33:03

标签: java 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;
  }
}

8 个答案:

答案 0 :(得分:9)

你在循环的每次迭代中调用wordsHash.keys(),这会在每次迭代时给你一个新的Enumeration<String> - 然后你再次调用它循环中

您希望将其称为一次,然后迭代单Enumeration<String>

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

请注意,由于您还获得了每个元素的值,因此最好迭代entrySet()而不是keys()

最好还是使用HashMap代替Hashtable,因为那时你可以使用增强的for循环......

答案 1 :(得分:8)

问题在于

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

每次循环时,您都会获得枚举的新副本。你需要获取一次密钥集,并迭代它。

在这里使用增强的for循环可能更容易

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

这应该提供您想要的行为,同时更简单,更容易阅读。

答案 2 :(得分:6)

问题是无论何时调用wordsHash.keys(),它都会返回一个新的枚举:

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

您需要做的是创建一个枚举并在整个循环中使用它。

P.S。你为什么使用Hashtable而不是HashMap

答案 3 :(得分:2)

.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();

}

答案 4 :(得分:1)

将您的代码更改为:

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

因此,每次进入循环时都不会创建指向HashTable的第一个键的新枚举。

答案 5 :(得分:0)

什么都没有修改wordsHash。这意味着,如果wordsHash.keys().hasMoreElements()为真,则对于程序的其余部分,它将继续为真。这会导致无限循环。您需要在进行时删除密钥,或者只需使用for

答案 6 :(得分:0)

每次循环迭代时,你得到一个新的Iterable ofer所有键:wordsHash.keys()只要其中至少有一个键,while循环永远不会结束。

替换:

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

通过

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

答案 7 :(得分:0)

此外,与您的枚举问题无关,这可能是一个缺陷:

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

这是java.lang.Integer与另一个java.lang.Integer的引用比较。它不是它们所代表的实际值的比较。它适用于“小”数字,因为自动装箱使用缓存的引用,但最终会破坏。你可能想要:

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