有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中的字典过滤和合并2个HashMap

我有一个映射,它有一个key-ItemType、一个enum和一组项名称(String)
Map<ItemType, Set<String> itemTypesAndNames;
例如,
键:ItemType1,值:a1、a2、a3
键:ItemType2,值:b1、b2、b3
键:ItemType3,值:c1、c2、C3

第二张地图是

Map<String, ItemId> itemNamesAndIds;

例如,
键:a1,值:1234556-434
键:a2,值:4324234-5453
键:b1值:3t5dgsfdfdsf
等等

我想用ItemType和一组ItemTypeID创建一个新映射
Map <ItemType, Set<ItemId>>
例如
键:ItemType1,值:1234556-434,4324234-545
关键字:ItemType2,值: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");
}

共 (2) 个答案

  1. # 1 楼答案

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

    我还修改了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;
        }
    }
    
  2. # 2 楼答案

    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收集器和合并功能来实现:

    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
        ));