1

次のコードがあります。

for (String helpId : helpTipFragCache.getKeys())
{
    List<HelpTopicFrag> value = helpTipFragCache.getValue(helpId);
    helpTipFrags.put(helpId, value);
}

helpTipFragCache には、キャッシュが空のときに値が必要な場合にキャッシュをロードするメカニズムがあります。getKeys() メソッドがこれをトリガーし、これが呼び出されるとキャッシュがロードされます。ただし、上記の場合、さまざまな動作が見られます。

最初にすばやくデバッグして、キャッシュが実際に (Eclipse 内で) 読み込まれているかどうかを確認しました。ステップスルーしましたが、for ループには入りませんでした (イテレータが空のため)。

次に、(同じコードを使用して) 再度デバッグし、getKeys() にステップインして、そこでプロセス全体を分析しました。その後、想定されていたすべてのことを実行し、反復子には反復する値があり、コンソールには平和がありました。

これを行うようにコードを変更して問題を修正しました。

Set<String> helpIds = helpTipFragCache.getKeys();
helpIds = helpTipFragCache.getKeys();
for (String helpId : helpIds)
{
    List<HelpTopicFrag> value = helpTipFragCache.getValue(helpId);
    helpTipFrags.put(helpId, value);
}

明らかに、デバッグによって何かが初期化または異なる動作を引き起こしましたが、これの原因を知っている人はいますか? 基本的に、返されたコレクションから反復子を作成するために何が起こっているのでしょうか?

その他の関連情報:

  • このコードは、サーバーの起動時に実行されます (tomcat)
  • このコードは、含まれている jar から実行すると期待どおりに動作しませんが、同じコード ベースにある場合は動作します
  • コレクションはセットです

編集

追加コード:

public Set<String> getKeys() throws Exception
    {
        if (CACHE_TYPE.LOAD_ALL == cacheType)
        {
            //Fake a getValue call to make sure the cache is loaded
            getValue("");
        }
        return Collections.unmodifiableSet(cache.keySet());
    }

public final T getValue(String key, Object... singleValueArgs) throws Exception
{
    T retVal = null;
    if (notCaching())
    {
        if (cacheType == CACHE_TYPE.MODIFY_EXISTING_CACHE_AS_YOU_GO)
        {
            retVal = getSingleValue(key, null, singleValueArgs);
        }
        else
        {
            retVal = getSingleValue(key, singleValueArgs);
        }
    }
    else
    {
        synchronized (cache)
        {
            if (needToLoadCache())
            {
                logger.debug("Need to load cache: " +  getCacheName());
                if (cacheType != CACHE_TYPE.MODIFY_EXISTING_CACHE_AS_YOU_GO)
                {
                    Map<String, T> newCache = null;
                    if (cacheType != CACHE_TYPE.MODIFY_EXISTING_CACHE)
                    {
                        newCache = getNewCache();
                    }
                    else
                    {
                        newCache = cache;
                    }
                    loadCache(newCache);
                    cache = newCache;
                }
                lastUpdatedInMillis = System.currentTimeMillis();
                forceLoadCache = false;
            }
        }
        ...//code in here does not execute for this example, simply gets a value that is already in the cache
    }

    return retVal;
}

元のクラス (前のコードが投稿された場​​所) に戻ります。

    @Override
    protected void loadCache(
            Map<String, List<HelpTopicFrag>>    newCache)
    throws Exception
    {
        Map<String, List<HelpTopicFrag>> _helpTipFrags = helpDAO.getHelpTopicFrags(getAppName(), _searchIds);
        addDisplayModeToFrags(_helpTipFrags);
        newCache.putAll(_helpTipFrags);
    }

上記では、キャッシュに入れる値を取得するためにデータベース呼び出しが行われています。

4

1 に答える 1

0

への答え

Basically, what is happening to create the iterator from the returned collection?

あなたの場合のforループは Iterable として扱いSet Iterable.iterator ()を呼び出して取得したIteratorを使用します。

Set as = ...;

for (A a : as) {
    doSth ();
}

基本的に同等です

Set as = ...;

Iterator hidden = as.iterator ();
while (hidden.hasNext ()) {
    a = hidden.next ();
    doSth ();
}
于 2012-11-15T21:35:44.183 に答える