关于java:TreeMap或HashMap更快

TreeMap or HashMap faster

本问题已经有最佳答案,请猛点这里访问。

我正在编写一个字典,它大量使用String作为Map中的键。 我关心的是HashMapTreeMap中的哪一个会在搜索地图中的键时产生更好(更快)的性能?


鉴于没有太多的碰撞,哈希映射将给你o(1)性能(有很多分裂,这可能会降级到潜在的O(n),其中N是任何一个桶中的条目数(colissions))。另一方面,如果您想要某种平衡的树结构来生成O(logN)检索,则使用TreeMaps。所以它真的取决于你的特定用例。但是如果你只想访问元素,不管它们的顺序如何都使用HashMap


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class MapsInvestigation {

public static HashMap<String, String> hashMap = new HashMap<String, String>();
public static TreeMap<String, String> treeMap = new TreeMap<String, String>();
public static ArrayList<String> list = new ArrayList<String>();

static {
    for (int i = 0; i < 10000; i++) {
        list.add(Integer.toString(i, 16));
    }
}


public static void main(String[] args) {
    System.out.println("Warmup populate");
    for (int i = 0; i < 1000; i++) {
        populateSet(hashMap);
        populateSet(treeMap);
    }
    measureTimeToPopulate(hashMap,"HashMap", 1000);
    measureTimeToPopulate(treeMap,"TreeMap", 1000);

    System.out.println("Warmup get");
    for (int i = 0; i < 1000; i++) {
        get(hashMap);
        get(treeMap);
    }
    measureTimeToContains(hashMap,"HashMap", 1000);
    measureTimeToContains(treeMap,"TreeMap", 1000);

}

private static void get(Map<String, String> map) {
    for (String s : list) {
        map.get(s);
    }

}

private static void populateSet(Map<String, String> map) {
    map.clear();
    for (String s : list) {
        map.put(s, s);
    }

}


private static void measureTimeToPopulate(Map<String, String> map, String setName, int reps) {
    long start = System.currentTimeMillis();
    for (int i = 0; i < reps; i++) {
        populateSet(map);
    }
    long finish = System.currentTimeMillis();
    System.out.println("Time to populate" + (reps * map.size()) +" entries in a" + setName +":" + (finish - start));
}

private static void measureTimeToContains(Map<String, String> map, String setName, int reps) {
    long start = System.currentTimeMillis();
    for (int i = 0; i < reps; i++) {
        get(map);
    }
    long finish = System.currentTimeMillis();
    System.out.println("Time to get()" + (reps * map.size()) +" entries in a" + setName +":" + (finish - start));
}
}

给出这些结果:

1
2
3
4
5
6
Warmup populate
Time to populate 10000000 entries in a HashMap: 230
Time to populate 10000000 entries in a TreeMap: 1995
Warmup get
Time to get() 10000000 entries in a HashMap: 140
Time to get() 10000000 entries in a TreeMap: 1164


HashMap是O(1)(通常)用于访问; TreeMap是O(log n)(保证)。

这假设您的密钥对象是不可变的,并且具有正确编写的equals和hashCode方法。有关如何正确覆盖equals和hashCode,请参阅Joshua Bloch的"Effective Java"第3章。


a HashMap是O(1)平均值,因此它应该更快,并且对于大型地图可能具有更好的吞吐量。
但是,当负载平衡变得太高时,HashMap需要重新散列。重复是O(n),因此在程序生命的任何时候,由于重新散列,您可能会遭受意外的性能损失,这在一些应用程序中可能是至关重要的[高延迟]。如果延迟是一个问题,那么在使用HashMap之前要三思而后行!

a HashMap也容易受到差的散列函数的影响,如果正在使用的许多项被散列到同一个地方,这可能会导致O(n)。


HashMap更快。但是,如果您经常需要按字母顺序处理字典,那么最好使用TreeMap,因为每次需要按字母顺序处理时,您需要对所有单词进行排序。

对于您的应用程序,HashMap是更好的选择,因为我怀疑您将经常需要按字母顺序排序的列表,如果有的话。