【发布时间】:2017-04-11 09:08:33
【问题描述】:
有没有办法搜索并获取包含在两个 HashMap 对象中的键子集?
到目前为止,我总是从哈希图进行迭代并在第二个中寻找匹配项。
我只是想知道是否有更聪明的方法来进行这种比较。
【问题讨论】:
有没有办法搜索并获取包含在两个 HashMap 对象中的键子集?
到目前为止,我总是从哈希图进行迭代并在第二个中寻找匹配项。
我只是想知道是否有更聪明的方法来进行这种比较。
【问题讨论】:
怎么样
List<String> listOne = new ArrayList<String>(mapOne.keySet());
List<String> listTwo = new ArrayList<String>(mapTwo.keySet());
List<String> listThree = new ArrayList<String>(listTwo);
listThree.retainAll(listOne);
CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)
【讨论】:
在复杂度小于 O(N) 的情况下无法做到这一点。您唯一能做的就是迭代最小的哈希图。
您可以做的另一件事是使用哈希图的键集并使用方法retainAll,它会为您执行交集,但复杂性不会改变。
【讨论】:
使用哈希集。如果您的用例需要(键,值)对,则同时维护一个 HashMap 和一个 HashSet,并且每当在 HashMap 中插入键时,也将其插入到 HashSet 中。否则,只需维护一个 HashSet。
然后你可以使用retainAll()函数找到两个集合的交集。
HashSet intersection = hashSet1.retainAll(hashSet2);
时间复杂度将为 O(n) 摊销。这与您正在执行的操作几乎相同,但这将使您的代码更加清晰和可读。
注意你可以维护一个List而不是Set,调用list的retainAll()方法。但是,List 的 retainAll() 将以 O(n^2) 复杂度运行,因为 List 的 contains() 方法运行在 O(n),而 HashSet 的 contains() 以 O(1) 摊销运行。
【讨论】:
您可以通过使用removeAll 删除所有键来创建newMap,如下所示,使用 inlin cmets:
Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>();
Set<Entry<String, String>> set1 = map1.entrySet();//get the entries from Map1
set1.removeAll(map2.entrySet());/remove all matched entries mateched in map2
Map<String, String> newMap = set1.stream().//convert set1 to Map using stream
collect(Collectors.toMap(Entry::getKey, Entry::getValue));
本示例使用Map<String, String>,但可以应用于任何类型(当然对于自定义类,您需要覆盖java.lang.Object 中的equals() 和hashcode() 方法)。
【讨论】:
可能不是最有效的方法,但这种 Java 8 单行代码可以工作
Map<Integer,Integer> mapA = ..... // your first map
Map<Integer,Integer> mapB = ..... // your second map
List<Integer> keys = mapA.entrySet().stream().filter((v) -> mapB.containsKey(v.getKey()))
.map(v -> v.getKey()).collect(Collectors.toList());
【讨论】: