给定:一张包含水果的地图
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"}]
]
同样,另一张包含蔬菜的地图
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"}]
]
我正试图结合篮子 水果篮 和 素食篮
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"}]
]
我的解决方案。
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());
}));
我试过方案一和方案二,我想知道是否有更好的方法来处理这个问题?
你可以这样做。
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; }
)
);
为什么不试着把合并解析为:
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;
}));
或者,如果内部地图是可变的,那么稍微方便一点,如
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;
}));
你必须创建可修改的列表来合并重复的键。
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;
}));
创建可修改的列表。
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;
}
输出。
{basket3=[{水果=[香蕉,橙子]},{蔬菜=[土豆,西红柿]}]。
basket2=[{FRUITS=[橙子,猕猴桃]},{VEGGIES=[洋葱,土豆]}]。
basket1=[{水果=[苹果、香蕉]}, {蔬菜=[番茄、洋葱]}]}。