Map <object,collection <object =“”>&gt;?</object,>有什么问题

时间:2013-04-05 15:22:02

标签: java data-structures map multimap

我正在尝试在Java中构建一个数据结构,我将插入大约200,000个字符串键,每个键的“平均值”为1000个整数Map<String, Arraylist<Integer>>。该地图最终将拥有大约2亿的价值。

问题在于插入时,我必须首先检查地图中是否存在该键,如果为true,则将所有值存储在临时集合中,然后将新整数添加到集合中并将它们放回到地图中,或使用新整数实例化一个新集合。

当我到达集合包含大约50000个整数的点时,这是非常慢的。我通常从堆空间错误中得到一个java。

有没有办法摆脱获取过程?我只检查密钥的存在,然后立即将值添加到现有的集合中,比如将资产放到堆栈中,特别是映射在内存中,或者它是什么使Java和C ++之间产生差异,在C ++中我可以从使用指针中受益吗?

保持这样一个事实:我不喜欢通过使用像multimaps这样的东西来增加地图的大小,因为结构看起来几乎是直截了当。

非常感谢提前。

2 个答案:

答案 0 :(得分:5)

如果您的代码实际上正在执行您的问题建议,那么您工作太辛苦了。一旦你的Key与ArrayList相关联。只需将ArrayList从地图中取出,然后将新整数添加到该列表中。你不需要“放回去”。只需更改列表即可获得对列表的引用。

    Map<String, ArrayList<Integer>> m = new HashMap<String, ArrayList<Integer>>();
    for ( int i = 0; i < 5; i++ ) {
        String key = ( i % 2 == 0 ) ? "Bob" : "Robert";
        ArrayList<Integer> l = m.get( key );
        if ( l == null ) {
            l = new ArrayList<Integer>();
            m.put( key, l );
        }
        l.add( i );
    }
    System.out.println( "m is " + m );

在我看来,Guava Multimap是解决这个问题的更好解决方案:http://guava-libraries.googlecode.com/svn/tags/release03/javadoc/com/google/common/collect/Multimap.html

答案 1 :(得分:2)

  1. 与HashMap调整大小相关的性能开销很大。当您使用no-arg构造函数创建新的HashMap时,其大小默认为16.您在其中放入了越来越多的元素,因此每当您超出可用空间时,都需要调整大小。调整大小涉及计算每个键的哈希码和哈希表之间的移动键。这是非常昂贵的。
  2. 如果你知道你的HashMap会存储很多密钥,你可以创建它的大小,例如200,000。

    1. ArrayList的默认容量为10。如果添加更多元素,则需要调整大小。这涉及创建新数组(ArrayList内部存储元素)并将旧数组中的元素复制到新数组。对于大型ArrayLists,这也可能非常昂贵。
    2. 我建议改用LinkedList。添加新元素非常便宜,因为元素存储为独立节点。但是,有一些缺点。有关详细信息,请参阅this question

      1. 您必须能够为200,000,000个对象预留足够的内存。正如Tom Hawtin所建议的那样,增加JVM使用的最大堆空间可能是必要的。 Java不是C ++,你不能只使用越来越多的内存。