Reputation: 393
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 Stream
s, but I would like to do it with Stream
s. Any help is appreciated. Thank you.
Upvotes: 4
Views: 576
Reputation: 21124
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())));
Upvotes: 4
Reputation: 17299
Other solution would be like this
list = gasType.entrySet()
.stream()
.map(m -> new AbstractMap.SimpleImmutableEntry<Integer, Long>(Integer.valueOf(m.getValue().split("-")[0]), m.getKey()))
.collect(Collectors.toList());
and second step:
list.stream()
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,Collectors.toCollection(TreeSet::new))));
or in one step:
gasType.entrySet()
.stream()
.map(m -> new AbstractMap.SimpleImmutableEntry<>(Integer.valueOf(m.getValue().split("-")[0]), m.getKey()))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.toCollection(TreeSet::new))))
Upvotes: 2
Reputation: 394116
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 Set
s, 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())));
Upvotes: 5