Reputation: 21
I have a nested Map of the following type LinkedHashMap<String, LinkedHashMap<String, ArrayList<Commit>>>
. The key of the first map stores some usernames, the key of the second map is a repository names of the users and inside the ArrayList I have an object with some attributes like hash, message, additions, etc.
After I sort alphabetically the whole collection by the key of the first map and the key of the second one how could I collect (save) my nested map in the new collection of the same type (the object remains unchanged)?
I need to do this using lambda and Stream API. Here is the way I am trying to do that:
LinkedHashMap<String, LinkedHashMap<String, ArrayList<Commit>>> sorted = gitUsers.entrySet()
.stream()
.sorted((u1, u2) -> u1.getKey().compareTo(u2.getKey()))
.map(u -> u.getValue()
.entrySet()
.stream()
.sorted((r1, r2) -> collator.compare(r1.getKey(), r2.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(a, b) -> a, LinkedHashMap::new));
I'm definitely doing something wrong because I keep getting the following message "Non-static method cannot be referenced from a static context" and can't collect the map. I guess I can't assemble my map successfully because of the .map()
function and the second stream I've used.
I know you would suggest me to use a TreeMap or to sort the collection and print it right away using .foreach()
method in my lambda (what I already did by the way), but I need to do it exactly that way like I've described above.
For the purposes of my Programming Fundamentals course this problem should be resolved that way. Hope for your help!
P.S. I was looking for the solution for a long period of time and did research everywhere including Stack Overflow forums and didn't find anything corresponding to the requested way of resolving the problem.
Upvotes: 1
Views: 2917
Reputation: 637
2 cents, I suggest you to try out EntryStream
provided StreamEx for Map Stream operations. Here is solution by my Fork of StreamEx.
StreamEx.of(gitUsers).sortedBy(Entry::getKey)
.toMap(Entry::getKey,
e -> EntryStream.of(e.getValue()).sortedBy(Entry::getKey).toMap(LinkedHashMap::new),
() -> new LinkedHashMap<>());
To me, the code is straightforward and shorter, and easier to understand. By the way, I think interface is always preferred. To me Map<String, Map<String, List<Commit>>>
is better.
Upvotes: 0
Reputation: 1528
Your code not compiled even I remove sorting by unknown collator
comparator.
Valid code is:
Map<String, Map<String, List<Commit>>> collect = h.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue()
.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a,
LinkedHashMap::new
)
),
(a, b) -> a,
LinkedHashMap::new
)
);
Note that you can replace with your comparator instead of Map.Entry.comparingByKey()
.
Upvotes: 5