I have a list of Station, in each Station there is a list of radios. I need to create a lookup Map of radio to Station. I know how to use Java 8 stream forEach to do it:
stationList.stream().forEach(station -> {
Iterator<Long> it = station.getRadioList().iterator();
while (it.hasNext()) {
radioToStationMap.put(it.next(), station);
}
});
But I believe there should be more concise way like using Collectors.mapping()
.
Anyone can help?
This should work and you don't need third parties.
stationList.stream()
.map(s -> s.getRadioList().stream().collect(Collectors.toMap(b -> b, b -> s)))
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Based on the question, considering the entities Radio
and Station
to be defined as:
@lombok.Getter
class Radio {
...attributes with corresponding 'equals' and 'hashcode'
}
@lombok.Getter
class Station {
List<Radio> radios;
... other attributes
}
One can create a lookup map from a List<Station>
as an input using a utility such as:
private Map<Radio, Station> createRadioToStationMap(final List<Station> stations) {
return stations.stream()
// create entries with each radio and station
.flatMap(station -> station.getRadios().stream()
.map(radio -> new AbstractMap.SimpleEntry<>(radio, station)))
// collect these entries to a Map assuming unique keys
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue));
}
Slightly different from this behaviour, if for same(equal) Radio
element across multiple Station
s, one wants to group all such stations, it can be achieved using groupingBy
instead of toMap
such as :
public Map<Radio, List<Station>> createRadioToStationGrouping(final List<Station> stations) {
return stations.stream()
.flatMap(station -> station.getRadios().stream()
.map(radio -> new AbstractMap.SimpleEntry<>(radio, station)))
// grouping the stations of which each radio is a part of
.collect(Collectors.groupingBy(AbstractMap.SimpleEntry::getKey,
Collectors.mapping(AbstractMap.SimpleEntry::getValue, Collectors.toList())));
}
If you are open to using a third-party library, there is the method groupByEach
from Eclipse Collections:
Multimap<Radio, Station> multimap =
Iterate.groupByEach(stationList, Station::getRadioList);
This can also be written using Java 8 Streams with the Collectors2
utility from Eclipse Collections:
Multimap<Radio, Station> multimap =
stationList.stream().collect(
Collectors2.groupByEach(
Station::getRadioList,
Multimaps.mutable.list::empty));
Note: I am a committer for Eclipse Collections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With