【发布时间】:2011-08-26 15:33:33
【问题描述】:
我有一个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 倍,但我认为它使用了更多内存。也许一些 cmets 基于这个假设?
// 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();
【问题讨论】:
-
您需要改进的主要内容是写入磁盘。这可能比你做的任何事情慢 100 倍。我会使用分析器来检查您将时间花在哪里。
-
那里几乎没有什么改进,我已经在使用带缓冲的 DataOutputStream,这是一种简单的顺序方法。正如我的微基准测试所示,排序和迭代会产生影响。
-
为什么说制作一个 ArrayList
> (例如)并对其进行排序比构建一个 TreeMap 需要更多的“复制”? -
"排序算法是一种改进的归并排序(如果低位子列表中的最高元素小于高位子列表中的最低元素,则忽略合并)。该算法提供了保证 n log( n) 性能。此实现将指定的列表转储到数组中,对数组进行排序,并迭代列表,从数组中的相应位置重置每个元素。这避免了尝试排序导致的 n2 log(n) 性能一个链表到位。”所以元素被复制到一个数组中。
标签: java list sorting queue hashmap