[英]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.