繁体   English   中英

在Java(或Scala)中迭代HashMaps的HashMap

[英]Iterating over a HashMap of HashMaps in Java (or Scala)

我创建了一个类Foo ,它具有返回Array<Int>的方法toArray()

现在,我有一个HashMap映射字符串到HashMaps,它将Objects映射到Foo。 那是:

HashMap<String,HashMap<Object,Foo>>

我想创建一个类型的新对象:

HashMap<String,HashMap<Object,Array<Int>>>

这是通过为原始HashMAp中的每个元素Foo调用函数toArray()获得的。

为此,我通常会这样做:

    public static HashMap<String,HashMap<Object,Array<Int>>> changeMap(Map mpOld) {
        Object key2;
        String key1;
        Iterator it2;
        HashMap<String,HashMap<Object,Array<Int>>> mpNew= 
            new HashMap<String,HashMap<Object,Array<Int>>>()
        Iterator it1 = mpOld.keySet().iterator();
        while (it1.hasNext()) {
            key1=it1.next();
            it2= mpOld.get(key1).keySet().iterator();
            mpNew.put(key1,new HashMap<Object,Array<Int>>())
            while (it2.hasNext()) {
                key2=it2.next();
                mpNew.get(key1).put(key2,mpOld.get(key1).get(key2).toArray());
                //TODO clear entry mpOld.get(key1).get(key2)
            }
            //TODO clear entry mpOld.get(key1)
        }
        return mpNew;
    }

类似的代码工作正常,但HashMap的大小太大,无法在内存中保存其中两个。 如你所见,我添加了两点,我想清除一些条目。 问题是,如果我这样做,我会得到一个并发错误,或者迭代器循环只是终止。

我想知道是否有更好的方法来迭代地图并复制信息。

此外,我正在使用Scala项目,但在这里我必须使用Java类型来解决一些兼容性问题。 虽然Java.util.HashMap不是迭代器,但Scala可能有一些隐藏的功能来处理这个问题?

谢谢,

迭代器提供remove(..)方法,可以安全地删除以前访问过的项目。 迭代地图的键/值条目,转换它们并将它们添加到新地图中,并在移动时删除旧地图。

/**
 * Transfers and converts all entries from <code>map1</code> to 
 * <code>map2</code>.  Specifically, the {@link Foo} objects of the 
 * inner maps will be converted to integer arrays via {@link Foo#toArray}.
 * 
 * @param map1 Map to be emptied.
 * @param map2 Receptacle for the converted entries.
 */
private static void transfer(Map<String, Map<Object, Foo>> map1
        , Map<String, Map<Object, int[]>> map2) {

    final Iterator<Entry<String, Map<Object, Foo>>> mapIt
        = map1.entrySet().iterator();
    while (mapIt.hasNext()) {
        final Entry<String, Map<Object, Foo>> mapEntry = mapIt.next();
        mapIt.remove();
        final Map<Object, int[]> submap = new HashMap<Object,int[]>();
        map2.put(mapEntry.getKey(), submap);
        final Iterator<Entry<Object,Foo>> fooIt 
            = mapEntry.getValue().entrySet().iterator();
        while (fooIt.hasNext()) {
            final Entry<Object,Foo> fooEntry = fooIt.next();
            fooIt.remove();
            submap.put(fooEntry.getKey(), fooEntry.getValue().toArray());
        }
    }
}

我没有时间检查它,但我想这样的东西应该适用于scala Maps(假设你使用scala 2.8,这终于在这里):

mpO.mapValues(_.mapValues(_.toArray))

它会占用你的外部地图,并用一个新地图“替换”所有内部地图,其中值是Int数组。 键和地图的一般“结构”保持不变。 根据scaladoc “生成的地图包裹原始地图而不复制任何元素。”,因此它不会是真正的替代品。

如果你也做了

import scala.collection.JavaConversions._

然后java映射可以像scala映射一样使用: JavaConversions包含一堆可以在scala和java集合之间转换的隐式方法。

BTW使用Map <String,HashMap <Object,Array <Int >>>最后可能不太方便,如果我是你,我会考虑引入一些隐藏这个结构复杂性的类。

编辑反映您的评论

import scala.collection.JavaConversions._
import java.util.Collections._

object MapValues {
  def main(args: Array[String]) {
    val jMap = singletonMap("a",singletonMap("b", 1))
    println(jMap)
    println(jMap.mapValues(_.mapValues(_+1)))
  }
}

打印:

{A = {B = 1}}
地图(a - >地图(b - > 2))

显示implicits非常适用于外部和内部地图。 这是JavaConversions对象的目的:即使您有一个java集合,您也可以将它用作类似的scala类(具有增强功能)。
您不必执行任何其他操作,只需导入JavaConversions._

例如,考虑字符串键; 让我们调用输入数据Map<String, Map<String, Object>> data

for (Entry<String, Map<String, Tuple>> entry : data.entrySet()) {
  String itemKey = entry.getKey();
  for (Entry<String, Object> innerEntry : entry.getValue().entrySet()) {
    String innerKey = innerEntry.getKey();
    Object o = innerEntry.getValue();
    // whatever, here you have itemKey, innerKey and o
  }
}

该集由地图支持,因此对地图的更改将反映在集中,反之亦然。 如果在对集合进行迭代时修改了映射(除了通过迭代器自己的remove操作),迭代的结果是未定义的。 该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。

为什么不在迭代器或set.remove (iterator.next ())上调用remove ()方法,其中iterator.next ()返回键,set是键集,迭代器是迭代器。

PS:还尝试重构你的数据结构,也许是一些处理数据检索的中间类? 地图中的数组作为值的地图没有说什么,很难跟踪。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM