在Java中过滤和合并2个HashMap的



我有一个Map,它有一个key - ItemType,一个enum和一组Item Names (String)
Map<ItemType, Set<String> itemTypesAndNames;

key: ItemType1, value: a1, a2, a3
key: ItemType2, value: b1, b2, b3
key: ItemType3, value: c1, c2, c 3

第二个映射是

Map<String, ItemId> itemNamesAndIds;


Key: a1, value: 1234556-434
Key: a2, value: 4324234-5453
Key: b1 value: 3t5dgsfdfdsf
以此类推

我想用ItemType和一组itemtypeid创建一个新的映射
Map <ItemType, Set<ItemId>>
eg
key: ItemType1, value: 1234556-434, 4324234-545
key: ItemType2, value: 3t5dgsfdfdsf
以此类推

public class ItemId {
private final String id;
public static ItemId of(String id) { 
return new ItemId (id)}
}
}
public enum ItemType {
ITEM_TYPE_1("ItemType1");
ITEM_TYPE_2("ItemType2");
}

这是一种方法。虽然我使用了一些流处理来准备一些演示数据,但我在最终解决方案中避免了它,以保持处理更有效(基于我的测试),因为我不知道你的地图的大小。

我也修改了你的enumclass,使它们能够使用。

首先,创建itemTypesAndNames映射。

Map<ItemType, Set<String>> itemTypesAndNames = Map.of(
ItemType.ITEM_TYPE_1,
Set.of("a1", "a2", "a3"),
ItemType.ITEM_TYPE_2,
Set.of("b1", "b2", "b3"),
ItemType.ITEM_TYPE_3,
Set.of("c1", "c2", "c3"));
itemTypesAndNames.entrySet().forEach(System.out::println);

打印

ITEM_TYPE_2=[b2, b1, b3]
ITEM_TYPE_3=[c1, c3, c2]
ITEM_TYPE_1=[a3, a2, a1]
现在创建itemNamesAndIds地图

Supplier<ItemId> itemId = () -> new ItemId(Integer
.toString((int)(Math.random() * 89999) + 10000));
Map<String, ItemId> itemNamesAndIds = itemTypesAndNames
.values().stream().flatMap(Set::stream)
.collect(Collectors.toMap(Function.identity(),
k -> itemId.get()));
itemNamesAndIds.entrySet().forEach(System.out::println);

打印

a1=83334
c3=99557
b2=18211
a2=91979
b3=41222
a3=78181
c1=38114
c2=56413
b1=68386

创建一个目标映射,简单地遍历类型和名称,创建如果名称存在于itemNamesAndIds映射中,则为该名称添加一个条目。computeIfAbsent如果目标set不存在,则创建它。

Map<ItemType, Set<ItemId>> typesAndIds = new HashMap<>();
for (Map.Entry<ItemType, Set<String>> e : itemTypesAndNames
.entrySet()) {
for (String name : e.getValue()) {
if (itemNamesAndIds.containsKey(name)) {
typesAndIds
.computeIfAbsent(e.getKey(),
v -> new HashSet<>())
.add(itemNamesAndIds.get(name));
}
}
}
typesAndIds.entrySet().forEach(System.out::println);

打印类似

的内容
ITEM_TYPE_3=[99557, 38114, 56413]
ITEM_TYPE_1=[83334, 78181, 91979]
ITEM_TYPE_2=[18211, 68386, 41222]

数据对象。

class ItemId {
private final String id;

public ItemId(String id) {
this.id = id;
}

public static ItemId of(String id) {
return new ItemId(id);
}

public String getId() {
return id;
}

public String toString() {
return id;
}
}
enum ItemType {
ITEM_TYPE_1("ItemType1"),
ITEM_TYPE_2("ItemType2"),
ITEM_TYPE_3("ItemType3");
private String itemType;
private ItemType(String t) {
this.itemType = t;
}

public String getType() {
return itemType;
}
}

Set<String>中的值应该重新映射到Set<ItemId>中(可能在itemNamesAndIds映射中只保留ids可用):

Map<ItemType, Set<ItemId>> remapped = itemTypesAndNames.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.filter(itemNamesAndIds::containsKey)
.map(itemNamesAndIds::get)
.collect(Collectors.toSet())
));

更新
如果两个具有相同结构Map<Key, Set<Value>>的映射必须合并,则可以使用toMap收集器与merge函数实现:

Map<Key, Set<Value>> map1 = ...; // init map1
Map<Key, Set<Value>> map2 = ...; // init map2
Map<Key, Set<Value>> merged = Stream.concat(
map1.entrySet().stream(), map2.entrySet().stream()
)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> { v1.addAll(v2); return v1; } // assuming that the sets are not immutable
));

最新更新