Java Sorting a Map using Steams VS TreeMap

Keet Sugathadasa :

Consider the following Java HashMap.

Map<String, String> unsortMap = new HashMap<String, String>();
unsortMap.put("Z", "z");
unsortMap.put("B", "b");
unsortMap.put("A", "a");
unsortMap.put("C", "c");

Now I wish to sort this Map by Key. One option is for me to use a TreeMap for this purpose.

Map<String, String> treeMap = new TreeMap<String, String>(unsortMap);

Another option is for me to Use Java Streams with Sorted(), as follows.

Map<String, Integer> sortedMap = new HashMap<>();
unsortMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));

Out of these two, which option is preferred and why (may be in terms of performance)?

Thank you

Valentin Ruano :

As pointed out by others dumping the sorted stream of entries into a regular HashMap would do nothing... LinkedHashMap is the logical choice.

However, an alternative to the approaches above is to make full use of the Stream Collectors API.

Collectors has a toMap method that allows you to provide an alternative implementation for the Map. So instead of a HashMap you can ask for a LinkedHashMap like so:

unsortedMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .collect(Collectors.toMap(
       Map.Entry::getKey,
       Map.Entry::getValue,
       (v1, v2) -> v1, // you will never merge though ask keys are unique.
       LinkedHashMap::new
    ));

Between using a TreeMap vs LinkedHashMap ... The complexity of construction is likely to be the same something like O(n log n)... Obviously the TreeMap solution is a better approach if you plan to keep adding more elements to it... I guess you should had started with a TreeMap in that case. The LinkedHashMap option has the advantage that lookup is going to be O(1) on the Linked or the original unsorted map whereas as TreeMap's is something like O(log n) so if you would need to keep the unsorted map around for efficient lookup whereas in if you build the LinkedHashMap you could toss the original unsorted map (thus saving some memory).

To make things a bit more efficient with LinkedHashMap you should provide an good estimator of the required size at construction so that there is not need for dynamic resizing, so instead of LinkedHashMap::new you say () -> new LinkedHashMap<>(unsortedMap.size()).

I'm my opinion the use of a TreeMap is more neat... as keeps the code smaller so unless there is actual performance issue that could be addressed using the unsorted and sorted linked map approach I would use the Tree.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=92309&siteId=1