【问题标题】:Merging multiple hashmaps合并多个哈希图
【发布时间】:2013-10-18 05:09:53
【问题描述】:

所以,我有两个 hashMaps

public HashMap<String, Integer> map1 = new HashMap<String,Integer>();

public HashMap<String, Integer> map2 = new HashMap<String,Integer>();

我想创建一个哈希图,它由这两个哈希图合并而成。

另外,当我向这两个哈希图中的任何一个添加元素时:

map1.put("key",1);

第三个 hashmap 应该有这个变化

解决方案:

import java.util.*;
public final class JoinedMap {
static class JoinedMapView<K,V> implements Map<K,V> {
    private final Map<? extends K,? extends V>[] items;
    public JoinedMapView(final Map<? extends K,? extends V>[] items) {
        this.items = items;
    }

    @Override
    public int size() {
        int ct = 0;
        for (final Map<? extends K,? extends V> map : items) {
            ct += map.size();
        }
        return ct;
    }

    @Override
    public boolean isEmpty() {
        for (final Map<? extends K,? extends V> map : items) {
            if(map.isEmpty()) return true;
        }
        return false;
    }

    @Override
    public boolean containsKey(Object key) {
        for (final Map<? extends K,? extends V> map : items) {
            if(map.containsKey(key)) return true;
        }
        return false;
    }

    @Override
    public boolean containsValue(Object value) {
        for (final Map<? extends K,? extends V> map : items) {
            if(map.containsValue(value)) return true;
        }
        return false;
    }

    @Override
    public V get(Object key) {
        for (final Map<? extends K,? extends V> map : items) {
            if(map.containsKey(key)){
                return map.get(key);
            }
        }
        return null;
    }

    @Override
    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public V remove(Object key) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        for (final Map<? extends K,? extends V> map : items) {
            map.clear();
        }
    }

    @Override
    public Set<K> keySet() {
        Set<K> mrgSet = new HashSet<K>();
        for (final Map<? extends K,? extends V> map : items) {
            mrgSet.addAll(map.keySet());
        }
        return mrgSet;
    }

    @Override
    public Collection<V> values() {
        Collection<V> values = new ArrayList<>();
        for (final Map<? extends K,? extends V> map : items) {
            values.addAll(map.values());
        }
        return values;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        throw new UnsupportedOperationException();
    }
}

/**
 * Returns a live aggregated map view of the maps passed in.
 * None of the above methods is thread safe (nor would there be an easy way
 * of making them).
 */
public static <K,V> Map<K,V> combine(
        final Map<? extends K, ? extends V>... items) {
    return new JoinedMapView<K,V>(items);
}

private JoinedMap() {
}
}

【问题讨论】:

  • @andras 这不是完全相同的副本。这里的问题是不同的。在将其作为重复项关闭之前,请仔细阅读该问题。
  • 我希望第三张地图能够对前两张地图进行任何更改。这样不行
  • 如果 map1 和 map2 都有 keyX 会怎样?当您执行 mergeMap.put(KeyNooneElseHas) 时会发生什么?
  • 你能解释一下你想达到什么目标吗?也许有更好的方法?
  • @mlk 提出了一些有趣的问题。您可能想要的是提供两个地图的“视图”,而不是在任一地图发生任何事情时必须维护的其他地图。 Guava Iterators.concat 可能是朝着正确方向迈出的一步......

标签: java map merge hashmap


【解决方案1】:

我认为这种方法是一个好的开始(当然你需要重写 HashMap 的 remove 和其他适当的方法):

class MyMergeAwareHashMap<K,V> extends HashMap<K,V> {
    HashMap<K, V> mergeMap

    public MyMergeAwareHashMap(Map<K, V> mergeMap) {
      this.mergeMap = mergeMap
    }

    @Override
    public Object put(K key, V value) {
      super.put(key, value)
      mergeMap.put(key, value)
    }
}

HashMap<String, Integer> mergedMap = new HashMap<String, Integer>()
MyMergeAwareHashMap<String, Integer> map1 = new MyMergeAwareHashMap<String, Integer>(mergedMap)
MyMergeAwareHashMap<String, Integer> map2 = new MyMergeAwareHashMap<String, Integer>(mergedMap)


map1.put('A', 1)
map2.put('B', 2)

println(map1.get('A')) // => 1
println(map1.get('B')) // => null

println(map2.get('A')) // => null
println(map2.get('B')) // => 2

println(mergedMap.get('A')) // => 1
println(mergedMap.get('B')) // => 2

【讨论】:

  • 奇怪的是,这在 groovy Web 控制台中不再起作用,但当我在本地运行时起作用。
  • 谢谢!这是一个简单的方法:)
【解决方案2】:

如果您不想手动更新第三张地图,则需要一个包装器,为其扩展哈希图

public class ExtHashMap<K, V> extends HashMap<K,V>{

    HashMap<K,V> map1,map2;

    public ExtHashMap(HashMap<k,V> _map1, HashMap<K,V> _map2){
       map1=_map1;
       map2=_map2;
    }

    //then override every method simulating merged map1,map2
    @Override
    public V get(Object key) { /* find in map1 or map2*/ }
}

【讨论】:

    【解决方案3】:

    您可以使用一张地图并根据您要读取的地图过滤检索到的数据。 这实际上取决于您要如何处理两个地图之间的碰撞。如果你不想发生冲突,你可以使用:

    private Map<String, Integer> map = newHashMap<>():
    
    void putInMap1(String key, Integer value) {
        map.put(key + "_1", value);
    }
    
    void putInMap2(String key, Integer value) {
        map.put(key + "_" + 1, value);
    }
    
    Integer getFromMap1(String key) {
         return map.get(key + "_1");
    }
    
    Integer getFromMap2(String key) {
         return map.get(key + "_2");
    }
    
    List<Integer> getFromMap3(String key) {
         List<Integer> res = new ArrayList<>();
         Integer map1Val = getFromMap1(key);
         if (map1Val != null) {
            res.add(map1Val);
         }
         Integer map2Val = getFromMap2(key);
         if (map2Val != null) {
            res.add(map2Val);
         }
         return res;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-23
      • 2018-10-31
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2013-05-04
      • 1970-01-01
      • 2011-07-31
      相关资源
      最近更新 更多