设置地图。迭代完成后输入值?
我可以在临时地图中保存地图。输入对象,然后在迭代完成后返回并更改其值吗?
例如,以下以两个步骤实现了一种交易。在步骤1中,递归处理条目的条目和条目地图(因此,一棵树)。条目被处理为新值,这些值将保存到临时地图,并由相应的地图键入。如果无一例外地计算所有条目,则步骤2就是简单地迭代临时地图并分配相应的新值。
void performPerilousProcedure(Object val) throws Exception
{
if (processing of val fails)
throw new Exception();
}
void recurivePerilousProcedure(Map someMap, Map tmp) throws Exception
{
Iterator<Map.Entry<String,Object>> iter1;
iter1 = someMap.entrySet().iterator();
while (iter1.hasNext()) {
Map.Entry<String,Object> entry1 = iter1.next();
Object val = entry1.getValue();
if (val instanceof Map) {
recursivePerilousProcedure((Map)val, tmp);
} else {
Object newval = performPerilousProcedure(val);
// ok to use Map.Entry as key across iter?
tmp.put(entry1, newval);
}
}
}
void doit(Map<String,Object> someMap) throws Exception
{
HashMap<Map.Entry<String,Object>,Object> tmp = new HashMap();
// Try to process map of entries and maps of entries and ma ...
recursivePerilousProcedure(someMap, tmp);
// All entries success processed, now simply assign new vals
Iterator<Map.Entry<String,Object>> iter2;
iter2 = tmp.keySet().iterator();
while (iter2.hasNext()) {
Map.Entry<String,Object> entry2 = iter2.next();
Object newval = tmp.get(entry2);
entry2.setValue(newval); // commit new value
}
}
问题是:
map.entry
用作 tmp
的对象可以在迭代外生存吗?
只要没有并发修改,这是MAP接口的有效使用吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
map.entry 对此非常清楚:
未定义的行为并不排除执行预期的事情,在实践中,当地图为
hashmap
或treemap
时,只要您不修改该实例地图(以不同的方式与调用setValue
在条目上)。问题是您是否要在这种实施特定的行为上构建应用程序,尽管长期以来尚未明确指定该应用程序。
还有另一个问题是,您将这些条目用作另一个地图中的键。条目的平等是由密钥和价值的组合确定的,但不是相关的映射。换句话说,如果不同地图的两个条目恰好具有相同的密钥和价值,那么您会发生冲突,并尝试将另一个条目放置在已经存在的条目中,但将其与新值相关联,而不是针对此条目(或更精确,不适合此目标图)。
更糟糕的是,您正在通过在输入实例中用作密钥时更改平等,通过在它们上调用
setValue
,绝对是非法的,然后将hashmap
转换为一个不一致的状态:如果您要做的一切,就是要迭代
tmp
一次,就不需要使用地图,因为不需要查找操作。list&lt; map.entry&lt; key,value&gt;&gt;
将做代替map&lt; key,value&gt;
,以保持密钥和值的组合,您可以迭代遍历。实际上,可以使用任何能够持有两个值的对象代替map.entry&lt; key,value&gt;
。如果将其替换为能够持有三个值的对象,则可以跟踪目标地图
,键和新值,然后在末尾执行简单的put
。因此,第一种方法可以看起来
依赖于实现细节,但是在调用
setValue
时,不需要地图查找。或干净的解决方案:根据您的应用程序,可能有第三种选择。只需在递归处理过程中构建一个与预期目标结构匹配的新地图,即可在未发生错误时替换原始图。
The documentation of
Map.Entry
is very clear about it:An undefined behavior does not preclude doing the intended thing and in practice, when the map is
HashMap
orTreeMap
, these entry instances keep working as long as you don’t modify the the map (in a different way than callingsetValue
on an entry).The question is whether you want to build your application on such an implementation specific behavior which, while longstanding, has not been specified explicitly.
There’s another problem in that you are using these entries as keys in another map. The equality of an entry is determined by the combination of key and value, but not the associated map. In other words, if two entries of different maps happen to have the same key and value, you have a clash and trying to put the other entry will keep the already existing entry but associate it with the new value not meant for this entry (or more precise, not meant for this target map).
Even worse, you are changing the equality while the entry instance is already in use as a key, by calling
setValue
on them, which is definitely illegal and turns theHashMap
into an inconsistent state:If all that you are going to do, is to iterate over
tmp
once, there is no need to use a map as no lookup operation is required. AList<Map.Entry<Key,Value>>
would do instead ofMap<Key,Value>
, to keep a combination of key and value you can iterate over. In fact, any object capable of holding two values could be used instead ofMap.Entry<Key,Value>
. If you replace it with an object capable of holding three values, you could keep track of the targetMap
, key, and new value and just perform a simpleput
at the end.So the first approach could look like
which is relying on the implementation detail but has the slight advantage that no map lookup is needed when calling
setValue
. Or the clean solution:Depending on your application, there might be a third option. Just build a new map matching the intended target structure during the recursive processing, to replace the original one when no error occurred.
如果我跟随,您可以做这样的事情:
If I'm following along, you can do something like this: