Java 根据键列表获取子 HashMap 的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28856781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 06:57:20  来源:igfitidea点击:

what is the best way to get a sub HashMap based on a list of Keys?

javahashmap

提问by aregnier

I have a HashMap and I would like to get a new HashMap that contains only the elements from the first HashMap where K belongs to a specific List.

我有一个 HashMap,我想获得一个新的 HashMap,它只包含第一个 HashMap 中的元素,其中 K 属于特定列表。

I could look through all the keys and fillup a new HashMap but I was wondering if there is a more efficient way to do it?

我可以查看所有的键并填充一个新的 HashMap,但我想知道是否有更有效的方法来做到这一点?

thanks

谢谢

回答by user1717259

If your keys have an ordering, you can use a TreeMap.

如果您的键有顺序,则可以使用 TreeMap。

Look at TreeMap.subMap()

看着 TreeMap.subMap()

It does not let you do this using a list, though.

但是,它不允许您使用列表来执行此操作。

回答by ControlAltDel

Depending on your usage, this may be a more efficient implementation

根据您的使用情况,这可能是更有效的实现

public class MapView {
  List ak;
  Map map;
  public MapView(Map map, List allowableKeys) {
     ak = allowableKeys;
     map = map;
  }
  public Object get(Object key) {
    if (!ak.contains(key)) return null;
    return map.get(key);
  }
}

回答by T.Gounelle

Yes there is a solution:

是的,有一个解决方案:

Map<K,V> myMap = ...;
List<K> keysToRetain = ...;
myMap.keySet().retainAll(keysToRetain);

The retainAlloperation on the Setupdates the underlying map. See java doc.

上的retainAll操作Set更新底层地图。请参阅Java 文档

EditBe aware this solution modify the Map.

编辑请注意此解决方案修改Map.

回答by kapex

Copy the map and remove all keys not in the list:

复制地图并删除不在列表中的所有键:

Map map2 = new Hashmap(map);
map2.keySet().retainAll(keysToKeep);

回答by Evgeniy Dorofeev

If you have Map m1 and List keys, then try following

如果您有 Map m1 和 List 键,请尝试以下操作

Map m2 = new HashMap(m1);
m2.keySet().retainAll(keys);

回答by helpermethod

Instead of looking through all keys you could loop over the list and check if the HashMap contains a mapping. Then create a new HashMap with the filtered entries:

您可以遍历列表并检查 HashMap 是否包含映射,而不是查看所有键。然后使用过滤后的条目创建一个新的 HashMap:

List<String> keys = Arrays.asList('a', 'c', 'e');

Map<String, String> old = new HashMap<>();
old.put('a', 'aa');
old.put('b', 'bb');
old.put('c', 'cc');
old.put('d', 'dd');
old.put('e', 'ee');

// only use an inital capacity of keys.size() if you won't add
// additional entries to the map; anyways it's more of a micro optimization
Map<String, String> newMap = new HashMap<>(keys.size(), 1f);

for (String key: keys) {
    String value = old.get(key);
    if (value != null) newMap.put(key, value);
}

回答by Bruno Paulino

you can use the clone() method on the K HashMap returned.

您可以在返回的 K HashMap 上使用 clone() 方法。

something like this:

像这样:

import java.util.HashMap;

public class MyClone {    
     public static void main(String a[]) {    
        Map<String, HashMap<String, String>> hashMap = new HashMap<String, HashMap<String, String>>();    
        Map hashMapCloned = new HashMap<String, String>();    

        Map<String, String> insert = new HashMap<String, String>();

        insert.put("foo", "bar");
        hashMap.put("first", insert);

        hashMapCloned.put((HashMap<String, String>) hashMap.get("first").clone());

    }    
}

It may have some syntax errors because I haven't tested, but try something like that.

它可能有一些语法错误,因为我还没有测试过,但请尝试类似的方法。

回答by geekprogrammer

No, because HashMap doesn't maintain an order of it's entries. You can use TreeMap if you need a sub map between some range. And also, please look at this question; it seems to be on the similar lines of yours.

不,因为 HashMap 不维护其条目的顺序。如果您需要某个范围之间的子地图,则可以使用 TreeMap。还有,请看这个问题;它似乎与你的相似。

回答by vtor

With a help of Guava.

在番石榴的帮助下。

Suppose you have a map Map<String, String>and want to submap with a values from List<String>list.

假设您有一个地图Map<String, String>并希望使用List<String>列表中的值进行子映射。

Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "4");

final List<String> list = Arrays.asList("2", "4");

Map<String, String> subMap = Maps.filterValues(
                map, Predicates.in(list));

Update / Note: As @assylias mentioned in the comment, you will have O(n) when using contains(). So if you have large list, this could have huge impact in performance.

更新/注意:正如评论中提到的@assylias,使用contains(). 因此,如果您的列表很大,这可能会对性能产生巨大影响。

On the other side HashSet.contains()is constant time O(1), so if there is a possibility to have Set instead of List, this could be a nice approach (notethat converting List to Set will cost O(n) anyway, so better not to convert :))

另一方面HashSet.contains()是恒定时间 O(1),所以如果有可能使用 Set 而不是 List,这可能是一个不错的方法(请注意,将 List 转换为 Set 无论如何都会花费 O(n),所以最好不要转变 :))

回答by Paul Boddington

You asked for a new HashMap. Since HashMapdoes not support structure sharing, there is no better approach than the obvious one. (I have assumed here that nullcannot be a value).

你要了一个新的HashMap. 由于HashMap不支持结构共享,没有比显而易见的更好的方法了。(我在这里假设它null不能是一个值)。

Map<K, V> newMap = new HashMap<>();
for (K k : keys) {
    V v  = map.get(k);
    if (v != null)
        newMap.put(k, v);
}

If you don't absolutely require that new object created is a HashMapyou could create a new class (ideally extending AbstractMap<K, V>) representing a restricted view of the original Map. The class would have two private final fields

如果您不是绝对要求创建的新对象是 ,则HashMap可以创建一个新类(理想情况下是扩展类AbstractMap<K, V>),表示原始Map. 该类将有两个私有 final 字段

Map<? extends K, ? extends V> originalMap;
Set<?> restrictedSetOfKeys;

The getmethod for the new Mapwould be something like this

get新的方法Map是这样的

@Override
public V get(Object k) {
    if (!restrictedSetOfKeys.contains(k))
        return null;
    return originalMap.get(k);
}

Notice that it is better if the restrictedSetOfKeysis a Setrather than a Listbecause if it is a HashSetyou would typically have O(1) time complexity for the getmethod.

请注意,如果restrictedSetOfKeys是 aSet而不是 a更好,List因为如果它是 a,HashSet您通常会对该get方法具有 O(1) 时间复杂度。