我有一个Map<byte[], Element>
,我想对它进行排序并将其写入磁盘,以便我有一个文件,其中所有元素都通过Guava的UnsignedBytes.lexicographicalComparator
按键排序。
我现在正在做的是:
HashMap<byte[], Element> memory;
// ... code creating and populating memory ...
TreeMap<byte[], Element> sortedMap = new TreeMap<byte[], Element>(UnsignedBytes.lexicographicalComparator());
sortedMap.putAll(memory.getMap());
MyWriter writer = new MyWriter("myfile.dat");
for (Element element: sortedMap.values())
writer.write(element);
writer.close();
可能很难使排序更快(O(nlogn)),问题是我是否可以改进排序列表的导航。理想情况下,我会分为ArrayList
而不是TreeMap
,因此迭代它会非常快。
我考虑过将HashMap放入ArrayList
和Collections.sort()
,但这需要比实际解决方案更多的复制。
有什么想法吗?
编辑:
我在这里添加ArrayList
的测试,速度提高了2倍,但我认为它使用的内存更多。也许对这个假设有一些评论?
// ArrayList-based implementation 2x faster
ArrayList<Element> sorted = new ArrayList<Element>(memory.size());
sorted.addAll(memory.values());
final Comparator<byte[]> lexic = UnsignedBytes.lexicographicalComparator();
Collections.sort(sorted, new Comparator<Element>(){
public int compare(Element arg0, Element arg1) {
return lexic.compare(arg0.getKey(), arg1.getKey());
}
});
MyWriter writer = new MyWriter(filename);
for (Element element: sorted)
writer.write(element);
writer.close();
答案 0 :(得分:1)
你的问题是“有什么想法吗?”。我想我能写的任何东西都是答案。
我遇到了与你相同的问题,并对这两个解决方案进行了广泛的基准测试:使用树形图,以便事先对项目进行排序,或者在事后对其进行排序。我的基准显示与您的结果相同。事后排序更快。
我不担心第二种方法需要更多复制。首先,速度越快越快,对吧?如果第二种方法占用较少的CPU周期,那么它会更好。
如果关注内存,请记住树图和散列图每个项目占用的内存远远多于ArrayList,后者由简单的对象数组支持。树形图或散列映射中的每个元素至少需要一个对象,通常更多。对象有很多开销,32个或更多字节。在平面数组中,每个元素只需4个字节。
我的基准测试显示,一旦你的数组大小超过几十个字节,从内存中分配数组的时间大致与数组的大小成正比。因此,如果ArrayList非常大,那么分配ArrayList可能会很慢。不过,我认为这是更好的选择,只要没有内存不足的危险。