Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert Map to List in Java 8

How to convert a Map<String, Double> to List<Pair<String, Double>> in Java 8?

I wrote this implementation, but it is not efficient

Map<String, Double> implicitDataSum = new ConcurrentHashMap<>();
//....
List<Pair<String, Double>> mostRelevantTitles = new ArrayList<>();
implicitDataSum.entrySet()
               .stream()
               .sorted(Comparator.comparing(e -> -e.getValue()))
               .forEachOrdered(e -> mostRelevantTitles.add(new Pair<>(e.getKey(), e.getValue())));

return mostRelevantTitles;

I know that it should works using .collect(Collectors.someMethod()). But I don't understand how to do that.

like image 686
Yakiv Holovko Avatar asked Jan 30 '16 21:01

Yakiv Holovko


People also ask

What is list of Map in Java?

A Map is an object that maps keys to values or is a collection of attribute-value pairs. The list is an ordered collection of objects and the List can contain duplicate values. The Map has two values (a key and value), while a List only has one value (an element).

Can we cast list to Map in Java?

With Java 8, you can convert a List to Map in one line using the stream() and Collectors. toMap() utility methods. The Collectors. toMap() method collects a stream as a Map and uses its arguments to decide what key/value to use.


2 Answers

Well, you want to collect Pair elements into a List. That means that you need to map your Stream<Map.Entry<String, Double>> into a Stream<Pair<String, Double>>.

This is done with the map operation:

Returns a stream consisting of the results of applying the given function to the elements of this stream.

In this case, the function will be a function converting a Map.Entry<String, Double> into a Pair<String, Double>.

Finally, you want to collect that into a List, so we can use the built-in toList() collector.

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet()
                   .stream()
                   .sorted(Comparator.comparing(e -> -e.getValue()))
                   .map(e -> new Pair<>(e.getKey(), e.getValue()))
                   .collect(Collectors.toList());

Note that you could replace the comparator Comparator.comparing(e -> -e.getValue()) by Map.Entry.comparingByValue(Comparator.reverseOrder()).

like image 134
Tunaki Avatar answered Oct 17 '22 03:10

Tunaki


Note that if you want efficient implementation, you should consider this:

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet()
                   .stream()
                   .map(e -> new Pair<>(e.getKey(), e.getValue()))
                   .collect(Collectors.toList());
mostRelevantTitles.sort(Comparators.comparing(Pair::getSecond, Comparator.reverseOrder()));

I assume that your Pair class have getSecond getter.

Using the sorted() stream pipeline step you create intermediate buffer, store everything to that buffer, convert it into array, sort that array, then store the result into the ArrayList. My approach, though less functional, stores data directly into the target ArrayList, then sorts it in-place without any additional copying. So my solution would take less time and intermediate memory.

like image 22
Tagir Valeev Avatar answered Oct 17 '22 03:10

Tagir Valeev