将哈希映射到磁盘的最快方法是排序集

时间:2011-05-16 17:48:50

标签: java list sorting queue hashmap

我有一个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放入ArrayListCollections.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();

1 个答案:

答案 0 :(得分:1)

你的问题是“有什么想法吗?”。我想我能写的任何东西都是答案。

我遇到了与你相同的问题,并对这两个解决方案进行了广泛的基准测试:使用树形图,以便事先对项目进行排序,或者在事后对其进行排序。我的基准显示与您的结果相同。事后排序更快。

我不担心第二种方法需要更多复制。首先,速度越快越快,对吧?如果第二种方法占用较少的CPU周期,那么它会更好。

如果关注内存,请记住树图和散列图每个项目占用的内存远远多于ArrayList,后者由简单的对象数组支持。树形图或散列映射中的每个元素至少需要一个对象,通常更多。对象有很多开销,32个或更多字节。在平面数组中,每个元素只需4个字节。

我的基准测试显示,一旦你的数组大小超过几十个字节,从内存中分配数组的时间大致与数组的大小成正比。因此,如果ArrayList非常大,那么分配ArrayList可能会很慢。不过,我认为这是更好的选择,只要没有内存不足的危险。