4

ハッシュテーブルを使用して、配列内で最も人気のある単語を見つけようとしています。何らかの理由で、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;
  }
}
4

8 に答える 8

10

ループの各反復で呼び出しwordsHash.keys()ているので、各反復で新鮮な結果が得られます。次に、ループEnumeration<String>で再度呼び出します。

あなたはそれを一度呼び出して、それからシングルを繰り返したいと思いますEnumeration<String>

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

entrySet()各要素の値も取得しているので、。よりも繰り返し処理する方がよいことに注意してくださいkeys()

の代わりに使用する方がよいでしょう。そうすれば、拡張されたforループ使用できます...HashMapHashtable

于 2013-01-30T19:37:14.520 に答える
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
    }

これにより、必要な動作が提供されると同時に、よりシンプルで読みやすくなります。

于 2013-01-30T19:36:38.903 に答える
6

問題は、を呼び出すたびwordsHash.keys()に、新しい列挙が返されることです。

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

あなたがする必要があるのは、単一の列挙を作成し、それをループ全体で使用することです。

PSなぜあなたは使っているのに使っHashtableていないのHashMapですか?

于 2013-01-30T19:36:46.490 に答える
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();

}
于 2013-01-30T19:37:33.320 に答える
1

コードを次のように変更します。

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

HashTableそのため、ループに入るたびにの最初のキーを指す新しい列挙が作成されるわけではありません。

于 2013-01-30T19:36:53.350 に答える
0

また、列挙の問題とは関係なく、これはおそらく欠陥です。

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

これは、java.lang.Integerと別のjava.lang.Integerの参照比較です。それらが表す実際の値の比較ではありません。自動ボクシングはキャッシュされた参照を使用するため、「小さい」数値で機能しますが、最終的には機能しなくなります。あなたはおそらく欲しい:

else if (wordsHash.get(currentWord) == mostPopularCount.intValue())
于 2013-01-30T19:43:17.540 に答える
0

を変更するものはありませんwordsHash。つまりwordsHash.keys().hasMoreElements()、一度trueの場合、プログラムの残りの部分でもtrueが継続されます。これにより、無限ループが発生します。進むにつれてキーを削除する必要があるか、または

于 2013-01-30T19:36:33.493 に答える
0

ループの反復ごとにすべてのキーの新しい Iterable を取得しますwordsHash.keys()。その中に少なくとも 1 つのキーがある限り、while ループは決して終了しません。

交換:

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

for (String currentWord: wordsHash.keys()){
于 2013-01-30T19:37:27.767 に答える