当需要按照键的自然顺序对元素进行排序时,可以使用TreeMap而不是HashMap。

7 浏览
0 Comments

当需要按照键的自然顺序对元素进行排序时,可以使用TreeMap而不是HashMap。

我需要一个支持三种操作的地图:插入、删除和按排序顺序迭代。这恰好是Java中TreeMap的接口。也就是说,可以使用HashMap并在每次迭代之前对其进行排序来实现。为了分析不同的方法,假设我执行了n次插入,m次删除,r次读取,然后进行迭代。\n使用TreeMap的实现如下:\nTreeMap tm = Maps.newTreeMap();\nfor (int i=0;i hm = Maps.newHashMap();\nfor (int i=0;i sortedList = Lists.newArrayList(hm.keySet()); // O(n-m)\nCollections.sort(sortedList); // O((n-m)*log(n-m))\nfor (Integer i : sortedList) {print(i);} // O(n-m)\n总之,我们总共的运行时间为O((n-m)*log(n-m))。\n对于所有的n、m,O(n*log(n) + m*log(m) + r*log(n-m)) > O((n-m)*log(n-m))。\n我的问题是,什么情况下TreeMap比HashMap更好?只有在需要多次迭代地图(假设为k次)的情况下才更好吗?如果k >> log(n),那么TreeMap的运行时间将是O(k*(n-m)),而HashMap的运行时间将是O(k*(n-m)*log(n-m))。无论如何,如果只执行O(log(n))次迭代(这听起来像一个合理的用例),HashMap的性能将优于TreeMap。我有什么遗漏吗?

0
0 Comments

当需要按照某个Comparator定义对Map进行排序时,可以使用TreeMap而不是HashMap。这不仅仅是为了性能的考虑。

对于性能方面,楼主已经提到了:使用HashMap并在迭代之前进行排序。

可以使用自定义的比较器对map的keySet进行排序。

我的观点是,楼主只关注性能方面。在某些情况下,并不是性能是首要需求,而是以某种有序方式保存数据。

我们关心的不是你如何保存数据,而是你可以用它做什么。如果我给你一个内部使用HashMap并在返回keySet之前使用数组排序的实现,你会像使用TreeMap一样满意。

我认为你没有看到整体情况。

我认为你的评论没有建设性。你只是表达了一个观点,没有提供任何进一步的论据。

0
0 Comments

当在读取密集型的情况下,使用TreeMap的优势在于只需要在插入时进行一次排序。与你的问题的假设相反,大多数情况下都是读取密集型的。

当你需要提取具有上下限的子映射、查找最小或最大的键,或者查找最接近给定键的键时,TreeMap提供了更大的优势。接口NavigableMap专门用于这些操作。

我编辑了我的问题以考虑到读取操作。HashMap中的读取操作为O(1),而在TreeMap中运行的读取操作为O(log(n))。

我们正在讨论迭代,在这里,通过“读取”我指的是“遍历映射”。

那是真的吗?有哪个应用程序比插入、删除和获取更频繁地遍历映射?我认为获取将是最常见的操作,而不是遍历。如果遍历是最常见的操作,那么你将从一个O(k*n) > O(n^2)的算法开始,这已经不方便了。

我可以理解为什么NavigableMap是有用的,如果你想使用树来实现它,那么没问题。我的问题是为什么TreeMap有用。

TreeMap实现了NavigableMap接口。

你在一个句子中提到整个应用程序,然后转而引用一个算法。一个应用程序通过引用在TreeMap中建立的状态来处理请求,通常它通过这种方式来处理许多请求,而这个状态只偶尔会更新。

好吧,我承认对于范围来说它是有用的,但它应该在文档中说明这个类只有在需要管理范围时才有用。

0