Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using streams to collect to Map

I have the following TreeMap:

TreeMap<Long,String> gasType = new TreeMap<>(); // Long, "Integer-Double"
gasType.put(1L, "7-1.50");
gasType.put(2L, "7-1.50");
gasType.put(3L, "7-3.00");
gasType.put(4L, "8-5.00");
gasType.put(5L, "8-7.00");
Map<Integer,TreeSet<Long>> capacities = new TreeMap<>);

The key is of the form 1L (a Long), and value of the form "7-1.50" (a String concatenation of an int and a double separated by a -).

I need to create a new TreeMap where the keys are obtained by taking the int part of the values of the original Map (for example, for the value "7-1.50", the new key will be 7). The value of the new Map would be a TreeSet containing all the keys of the original Map matching the new key.

So, for the input above, the value for the 7 key will be the Set {1L,2L,3L}.

I can do this without Streams, but I would like to do it with Streams. Any help is appreciated. Thank you.

like image 502
Nizamuddin Shaikh Avatar asked Dec 17 '22 23:12

Nizamuddin Shaikh


2 Answers

Here's one way to do it:

Map<Integer,TreeSet<Long>> capacities = 
  gasType.entrySet()
         .stream ()
         .collect(Collectors.groupingBy (e -> Integer.parseInt(e.getValue().substring(0,e.getValue ().indexOf("-"))),
                                         TreeMap::new,
                                         Collectors.mapping (Map.Entry::getKey,
                                                             Collectors.toCollection(TreeSet::new))));

I modified the original code to support integers of multiple digits, since it appears you want that.

This produces the Map:

{7=[1, 2, 3], 8=[4, 5]}

If you don't care about the ordering of the resulting Map and Sets, you can let the JDK decide on the implementations, which would somewhat simplify the code:

Map<Integer,Set<Long>> capacities = 
  gasType.entrySet()
         .stream ()
         .collect(Collectors.groupingBy (e -> Integer.parseInt(e.getValue().substring(0,e.getValue ().indexOf("-"))),
                                         Collectors.mapping (Map.Entry::getKey,
                                                             Collectors.toSet())));
like image 89
Eran Avatar answered Dec 29 '22 12:12

Eran


You may try this out,

final Map<Integer, Set<Long>> map = gasType.entrySet().stream()
        .collect(Collectors.groupingBy(entry -> Integer.parseInt(entry.getValue().substring(0, 1)),
                Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));

UPDATE

If you want to split the value based on "-" since there may be more that one digit, you can change it like so:

final Map<Integer, Set<Long>> map = gasType.entrySet().stream()
        .collect(Collectors.groupingBy(entry -> Integer.parseInt(entry.getValue().split("-")[0]),
                Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));
like image 27
Ravindra Ranwala Avatar answered Dec 29 '22 12:12

Ravindra Ranwala