为什么已填充的按需集合上的迭代器为空



我有以下代码:

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);
}

上面,进行了一个数据库调用以获取要放入缓存中的值。

的答案

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

在您的案例中,for循环将Set视为Iterable,并使用通过调用Iterable.Iterator()获得的Iterator。

Set as = ...;
for (A a : as) {
doSth ();
}

基本上等同于

Set as = ...;
Iterator hidden = as.iterator ();
while (hidden.hasNext ()) {
a = hidden.next ();
doSth ();
}

最新更新