I am writing an dictionary that make heavily use of String as key in Map<String, Index>
. What I concern is which one of HashMap
and TreeMap
will result in better (faster) performance in searching a key in the map?

- 2,921
- 2
- 25
- 38
-
2Check here - http://stackoverflow.com/questions/302371/which-data-structure-would-you-use-treemap-or-hashmap-java – Bhesh Gurung Aug 14 '11 at 14:43
-
1you should first define 'faster' do you want better throughput? [can process more items per second] or better [smaller] latency [maximum time to get an answer per OP]? – amit Aug 14 '11 at 14:53
-
@amit it's a dictionary, so it has to be latency. – toto2 Aug 14 '11 at 14:56
-
@amit: "faster" here means the time the map will find the key (`String`) and return the result. Because String has `hashCode` and `order` so I just don't know which one should I use. – Genzer Aug 14 '11 at 15:02
-
1@Genzer: what I meant was: do you prefer a map that USUALLY work faster, but sometimes, unexpectedly, will take much longer time? or something predictable, which you know exactly how much time each op will take, but is slower then the average of the faster map? – amit Aug 14 '11 at 15:05
-
@amit: I've read your answer. The information of HashMap will rehash if Load Balance is too high is very useful. Because I use the map as caching, so I think I would go for HashMap. – Genzer Aug 14 '11 at 15:30
5 Answers
Given that there are not many collissions hashmaps will give you o(1) performance (with a lot of colissions this can degrade to potentially O(n) where N is the number of entries (colissions) in any single bucket). TreeMaps on the other hand are used if you want to have some sort of balanced tree structure which yields O(logN) retrieval. So it really depends on your particular use-case. But if you just want to access elements, irrespective of their order use HashMap

- 3,121
- 3
- 30
- 44
-
3Small note, in java8 hashmaps will degrade to O(log n) instead of O(n) http://javarevisited.blogspot.be/2016/01/how-does-java-hashmap-or-linkedhahsmap-handles.html – Pieter De Bie Dec 19 '17 at 09:59
-
3
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));
}
}
Gives these results:
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 is O(1) (usually) for access; TreeMap is O(log n) (guaranteed).
This assumes that your key objects are immutable and have properly written equals and hashCode methods. See Joshua Bloch's "Effective Java" chapter 3 for how to override equals and hashCode correctly.

- 305,152
- 44
- 369
- 561
-
3
-
Link is dead, http://web.archive.org/web/20110626160836/http://www.coderfriendly.com/wp-content/uploads/2009/05/java_collections_v2.pdf – RedShift Dec 13 '17 at 09:00
-
Fixed it with one that works. Please find a better way to boost your rep here than looking at 6 year old links. – duffymo Dec 13 '17 at 12:51
a HashMap
is O(1) average, so it is supposed to be faster, and for large maps will probably have better throughput.
However, a HashMap
requires rehashing when Load Balance become too high. rehashing is O(n), so at any time of the program's life, you may suffer unexpectedly performance loss due to rehash, which might be critical in some apps [high latency]. So think twice before using HashMap
if latency is an issue!
a HashMap
is also vulnerable to poor hashing functions, which might cause O(n), if many items in use are hashed into the same place.

- 175,853
- 27
- 231
- 333
-
4
-
1@toto2 Yes, though it's not hard to deliberately generate strings that will be distributed very poorly among the hash buckets. Not a very practical attack vector, but it's maybe interesting to know. – ddekany Nov 30 '17 at 16:58
HashMap is faster. However if you would often need to process your dictionary in alphabetical order, you would be better off with the TreeMap since you would otherwise need to sort all your words every time you need to process them in alphabetical order.
For your application HashMap is the better choice since I doubt you will need the alphabetically sorted list often, if ever.

- 5,306
- 21
- 24