Reputation: 49
Given: A Map containing FRUITS
enum Food{
FRUITS, VEGGIES;
}
Map<String, Map<Food, List<String>>> fruitBasket= new HashMap<>();
fruitBasket.put("basket1", Collections.singletonMap(Food.FRUITS, Arrays.asList("apple","banana")));
fruitBasket.put("basket2", Collections.singletonMap(Food.FRUITS, Arrays.asList"orange", "kiwi")));
fruitBasket.put("basket3", Collections.singletonMap(Food.FRUITS, Arrays.asList("banana", "orange")));
fruitBasket:
[
basket1, [Food.FRUITS, {"apple", "banana"}],
basket2, [Food.FRUITS, {"orange", "kiwi"}],
basket3, [Food.FRUITS, {"banana", "orange"}]
]
Similarly another map containing VEGGIES
Map<String, Map<Food, List<String>>> veggieBasket= new HashMap<>();
veggieBasket.put("basket1", Collections.singletonMap(Food.VEGGIES, Arrays.asList("Tomato","Onion")));
veggieBasket.put("basket2", Collections.singletonMap(Food.VEGGIES, Arrays.asList("Onion", "Potato")));
veggieBasket.put("basket3", Collections.singletonMap(Food.VEGGIES, Arrays.asList("Potato", "Tomato")));
veggieBasket:
[
basket1, [Food.VEGGIES, {"Tomato","Onion"}],
basket2, [Food.VEGGIES, {"Onion", "Potato"}],
basket3, [Food.VEGGIES, {"Potato", "Tomato"}]
]
I am trying to combine the baskets fruitBasket and veggieBasket
Final output: should look something like below
groceryBasket
[
basket1, [Food.FRUITS, {"apple", "banana"}, Food.VEGGIES, {"Tomato","Onion"}],
basket2, [Food.FRUITS, {"orange", "kiwi"}, Food.VEGGIES, {"Onion", "Potato"}],
basket3, [Food.FRUITS, {"banana", "orange"}, Food.VEGGIES, {"Potato", "Tomato"}]
]
MySolution:
Solution 1:
Map<String, Map<Food, List<String>>> groceryBasket= new HashMap<>();
grocery basket = Stream.concat(fruitBasket.entrySet().stream(), veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (fruitList, veggieList ) ->
{
final List<String> groceryList = new ArrayList<>();
groceryList .addAll(fruitList);
groceryList .addAll(veggieList);
return groceryList;
}));
Solution 2:
Map<String, Map<Food, List<String>>> groceryBasket= new HashMap<>();
grocery basket = Stream.concat(fruitBasket.entrySet().stream(), veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (fruitList, veggieList ) ->
{
return Stream.of(fruitList, veggieList).flatMap(x -> x.stream()).collect(Collectors.toList());
}));
I tried Solutions 1 and Solution 2, I was trying to thing if there is a better/optimized way to handle this?
Upvotes: 4
Views: 322
Reputation: 31868
Why not try resolving the merge as:
Map<String, Map<Food, List<String>>> groceryBasket =
Stream.concat(fruitBasket.entrySet().stream(), veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
Map<Food, List<String>> innerMap = new HashMap<>(a);
innerMap.putAll(b);
return innerMap;
}));
or if the inner map is mutable then slightly convenient as
Map<String, Map<Food, List<String>>> groceryBasket = Stream.concat(fruitBasket.entrySet().stream(),
veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
a.putAll(b);
return a;
}));
Upvotes: 1
Reputation: 17289
You can do like this:
Map<String, Map<Food, List<String>>> groceryBasket =
Stream.concat(fruitBasket.entrySet().stream(),veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, v -> v.getValue().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
(a, b) -> { a.putAll(b);return a; }
)
);
Upvotes: 3
Reputation: 7165
You have to create modifiable List for merging duplicate keys,
Stream.concat(fruitBasket.entrySet().stream(), veggieBasket.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, e -> listOf(e.getValue()),
(left, right) -> {
left.addAll(right);
return left;
}));
To create modifiable List,
public static List<Map<Food, List<String>>> listOf(Map<Food, List<String>> a) {
final ArrayList<Map<Food, List<String>>> list = new ArrayList<>();
list.add(a);
return list;
}
Output:
{basket3=[{FRUITS=[banana, orange]}, {VEGGIES=[Potato, Tomato]}],
basket2=[{FRUITS=[orange, kiwi]}, {VEGGIES=[Onion, Potato]}],
basket1=[{FRUITS=[apple, banana]}, {VEGGIES=[Tomato, Onion]}]}
Upvotes: 0