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
what is the best way to get a sub HashMap based on a list of Keys?
提问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
回答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
回答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 HashMap
does not support structure sharing, there is no better approach than the obvious one. (I have assumed here that null
cannot 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 HashMap
you 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 get
method for the new Map
would 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 restrictedSetOfKeys
is a Set
rather than a List
because if it is a HashSet
you would typically have O(1) time complexity for the get
method.
请注意,如果restrictedSetOfKeys
是 aSet
而不是 a更好,List
因为如果它是 a,HashSet
您通常会对该get
方法具有 O(1) 时间复杂度。