treemap vs hashmap并根据内存使用情况进行排序

时间:2014-05-14 06:53:38

标签: java collections

我有一个格式很大的文件:

x a
y c
x d
z a
z s
y k

我希望输出排序并且格式为

x a,d
y c,k
z a,s,k

对于这种类型的任务,哈希是最好的:

直截了当的TreeMap解决方案是:

Map<String, StringBuilder> agg = Maps.newTreeMap();

while ((line = r.readLine()) != null) {

    String[] arr = line.split("\t");
            String key = arr[0];
            String value = arr[1];

    if(agg.containsKey(key)) {
            agg.get(key).append(",").append(value);
        }
        else {
            agg.put(key, new StringBuilder(value));
        }
    }

}
r.close();


System.out.println("Printing results");
FileWriter f = new FileWriter("out.txt");

for (String key : agg.keySet()) {
    f.write(key+"\t"+agg.get(key)+"\n");
}

另一种选择是使用hashmap,获取键集,对其进行排序并对其进行迭代。

不同的部分是

    System.out.println("Sorting array");
    List<String> keys = Lists.newArrayList(agg.keySet());
            Collections.sort(keys);
        System.out.println("Printing results");
        FileWriter f = new FileWriter("out.txt");

        for (String key : keys) {
            f.write(key+"\t"+agg.get(key)+"\n");
        }

对我来说,大O不太重要,因为它是一个批处理工作。

对我而言,内存使用更为重要。

哪种策略在内存方面更有效?

HashMap以及排序阶段或TreeMap方法中的窥视

3 个答案:

答案 0 :(得分:2)

HashMap 在内存利用率方面不是最佳,而是针对特定操作。它由一个数组支持,该数组在初始化时分配,并在其大小达到一定限制时调整大小。因此,急切地分配内存。它的大小始终是2的幂,这实际上是更快的桶指数计算的计算优化。因此,(未使用的)分配的内存可能会大大超过程序使用的实际内存。

TreeMap 提供了最佳的内存利用率,与HashMap相比,在获取,添加,删除操作方面的性能更差。这种构造函数更加明显,它没有任何可能影响其计算复杂性的参数。它的所有条目都被懒惰地分配并与现有条目相关联以形成树。

答案 1 :(得分:1)

如果是批处理作业,TreeMap将不会使用HashMap之类的额外内存。 HashMap的默认加载系数是我认为的0.75(即在大小增加之前地图可以达到75%)。

如果O(log n)(IIRC)不成为瓶颈,那么TreeMap也会更加直截了当。如果是,您可以将List与您自己的Tuple对象和自定义Comparator一起使用,但之后您不会获得O(1)get()。< / p>

答案 2 :(得分:1)

由于唯一密钥的数量是未知的,并且可能很大,如果密钥的数量超过散列表的初始容量的乘积,则基于散列的方法可能消耗更多的存储器。它的负载系数。因为在这样的事件中,容量只会增加一倍,增加内存使用量。