I'm dealing with a complex bit of logic that I can't get right. I'm trying to reduce a list that contains a list of properties into a one merged object, removing duplicate keys.
Say I have a Config
class with the following elements:
private int index;
private String name;
private Map<String, String> properties;
This object will be in a linked list of objects, List<Config>
. If the Config
object at index 5 has a key/value in properties
of "version=2", but the Config
object at index 1 has properties
that contain "version=1", I need the property in index 5 to win. So I want one final Config
(I'll worry about the name
element later) that has merged properties that reflect the latest properties in the stream.
Am I asking for too much in one operation? So far I've come up with something like this, but it doesn't compile:
configList.stream()
.map(it -> it.getProperties())
.collect(Collectors.toCollection(() ->
new TreeSet<>(Comparator.comparing(???))))
Any help appreciated!
If I understand the question correctly, you want to get all the properties and merge them into one Map and if there is duplicate, you want to prioritise the property of map with highest index value in config.
This is the solution I came up with.
Map<String, String> properties = configList.stream()
.sorted(Comparator.comparingInt(Config::getIndex)) //Sort the configs in ascending order by indexes.
.flatMap(config -> config.properties.entrySet().stream()) //flat map all the properties
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (left, right) -> right)); //collect to a map
This Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (left, right) -> right)
is where the magic happens.
Since we already sorted the configs by index, we will always have the value with higher config index at bottom and all we do is overwrite the existing key when duplicate key occurs.