我有一个格式很大的文件:
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方法中的窥视
答案 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)
由于唯一密钥的数量是未知的,并且可能很大,如果密钥的数量超过散列表的初始容量的乘积,则基于散列的方法可能消耗更多的存储器。它的负载系数。因为在这样的事件中,容量只会增加一倍,增加内存使用量。