Reputation: 7165
I have a Map
as below,
Map<String, Map<String, String>> dateFormatsMap;
Map<String,String> m1 = Map.of("A","DD", "B", "MM", "C","YY");
Map<String,String> m2 = Map.of("A","DD-MM", "X", "MM", "C","YYYY");
Map<String,String> m3 = Map.of("X","DD", "Y", "MM", "C","YY");
dateFormatsMap = Map.of("P2",m2,"P1",m1, "p3",m3);
This map is populated from DB and has project-wise data.
What I want is to get merged Map
of a specific project and one default project and in case of a duplicate, I want to keep values of a specified project.
I tried below code,
private static Map<String, String> getFormats(String project) {
Set<String> projects = Set.of("P1", project); //e.g "P1" as default project
return dateFormatsMap.entrySet().stream()
.filter(e->projects.contains(e.getKey()))
.flatMap(e->e.getValue().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(o,n)->o));
}
I call this method as,
getFormats("P2");
But this gives the varying results having values sometimes from "P1" and sometimes from "P1".
{A=DD, B=MM, C=YY, X=MM}
{A=DD-MM, B=MM, C=YYYY, X=MM}
I need to have a fixed result as,
{A=DD-MM, B=MM, C=YYYY, X=MM}
You can check ideone
I hope, I have detailed the question. I appreciate any help.
Upvotes: 1
Views: 172
Reputation: 31858
One way to deal with this without using Stream
s, you could also seek is using putAll
-
private static Map<String, String> getFormats(String project) {
Map<String, String> baseProjFormats = dateFormatsMap.get("P1");
Map<String, String> currentProjFormats = dateFormatsMap.getOrDefault(project, Collections.emptyMap());
baseProjFormats.putAll(currentProjFormats);
return baseProjFormats;
}
Upvotes: 1
Reputation: 1579
I'm just going to be the guy who doesn't use streams:
public static void main(String[] args) {
Map<String, String> defaultMap = Map.of("A", "DD", "B", "MM", "C", "YY");
Map<String, String> mapToMerge = Map.of("A", "DD-MM", "X", "MM", "C", "YYYY");
// Do the magic
Map<String, String> result = new HashMap<String, String>();
result.putAll(mapToMerge);
for (Map.Entry<String, String> entry : defaultMap.entrySet())
if (!result.containsKey(entry.getKey()))
result.put(entry.getKey(), entry.getValue());
// Print results
result.entrySet().stream().forEach(System.out::println);
}
Upvotes: 0
Reputation: 3184
I added all from the default project which are not in the specific project map and afterwards added everything from the specific project map:
private static Map<String, String> getMyFormats(String project) {
String defaultProject = "P1";
Map<String, String> specificMap = dateFormatsMap.get(project);
Map<String, String> collect = dateFormatsMap.get(defaultProject).entrySet().stream()
.filter(e -> !specificMap.containsKey(e.getKey()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
collect.putAll(specificMap);
return collect;
}
or using collectingAndThen
:
private static Map<String, String> getFormats(String project) {
String defaultProject = "P1";
Map<String, String> collect = dateFormatsMap.get(defaultProject).entrySet().stream()
.filter(e -> !dateFormatsMap.get(project).containsKey(e.getKey()))
.collect(collectingAndThen(
toMap(Map.Entry::getKey, Map.Entry::getValue),
map -> {
map.putAll(dateFormatsMap.get(project));
return map;
})
);
return collect;
}
Upvotes: 1
Reputation: 7165
I got the solution. Created two maps and then merged as below,
private static Map<String, String> getFormats(String project) {
Map<String, String> baseProjFormats = dateFormatsMap.get("P1");
Map<String, String> currentProjFormats = dateFormatsMap.get(project);
return Stream.of(baseProjFormats, currentProjFormats)
.flatMap(e -> e.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(o, n) -> n));
}
I would welcome any better solution.
Upvotes: 0