如何在Java中从地图中获取子地图

94 阅读3分钟

在Java中,子图是给定的Map在特定范围内的键之间的部分或一部分。本文将讨论Map中获取子图的不同技术

1.使用Map.keySet().retainAll()

retainAll()Map中删除所有不存在于指定列表中的键。要注意的是,retainAll() 删除的是原始集合中的条目,所以如果我们不想修改原始Map,就Map的一个新副本上执行这个操作。

Map<String, String> map = new HashMap<>();
map.put("key1", "Value1");
map.put("key2", "Value2");
map.put("key3", "Value3");

List<String> keysToRetain = List.of("key1", "key2");
map.keySet().retainAll(keysToRetain);

System.out.println(map);    //{key1=Value1, key2=Value2}

2.使用TreeMap的submap()headMap()tailMap()

TreeMap类存储了按键排序的键值对,可以是自然顺序,也可以使用提供者的比较器进行自定义排序。TreeMap允许使用以下方法获得一个子图。

  • subMap(fromKey, toKey): 返回该地图中键值范围从fromKey (包括)到toKey (包括)的部分的视图。
  • headMap(toKey): 返回该地图中键值严格小于toKey 的部分的视图。
  • tailMap(fromKey): 返回该地图中键值大于或等于fromKey 的部分的视图。

我们也可以将这些方法用于其他Map实现的SortedMapNavigableMap

TreeMap<String, String> treeMap = new TreeMap<>();

treeMap.put("key1", "Value1");
treeMap.put("key2", "Value2");
treeMap.put("key3", "Value3");

SortedMap<String, String> subMap = treeMap.subMap("key2", "key3");      //{key2=Value2}
SortedMap<String, String> headMap = treeMap.headMap("key2");            //{key1=Value1}
SortedMap<String, String> tailMap = treeMap.tailMap("key2");           //{key2=Value2, key3=Value3}

请注意,下面的每个方法都会返回一个由原始地图支持地图,所以子地图的变化会反映在原始地图中,反之亦然。

subMap.put("key2", "NEW_VALUE_2");

System.out.println(subMap);     //{key2=NEW_VALUE_2}
System.out.println(treeMap);    //{key1=Value1, key2=NEW_VALUE_2, key3=Value3}

同样,向原始地图添加新条目也会改变地图的视图。例如,在原始地图中添加一个新的键值对key4:value4会反映在所有子地图的视图中。

treeMap.put("key4", "value4");

System.out.println(tailMap);     //{key2=NEW_VALUE_2, key3=Value3, key4=value4}
System.out.println(treeMap);    //{key1=Value1, key2=NEW_VALUE_2, key3=Value3, key4=value4}

3.使用API

一个流是来自源的数据的集合或序列。我们可以使用Stream API来遍历过滤收集所需的键值对到一个新的Map

新的地图没有原始地图支持,所以我们可以改变两个地图中的条目而不改变另一个地图

Map<Integer, String> hashmap = new HashMap<>();
hashmap.put(1, "Value1");
hashmap.put(2, "Value2");
hashmap.put(3, "Value3");

List<Integer> keysList = Arrays.asList(1, 2);

Map<Integer, String> subHashmap = hashmap.entrySet()
        .stream()
        .filter(x -> keysList.contains(x.getKey()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

System.out.println(subHashmap);     //{1=Value1, 2=Value2}

4.使用Guava的地图

Guava是一套标准库,提供各种实用方法。它的Maps类提供了以下实用方法,通过从指定的Map中过滤键或值来获得一个新的Map

  • Maps.filterKeys(unfilteredMap, keyPredicate)
  • Maps.filterValues(unfilteredMap, valuePredicate)
  • Maps.filterEntries(unfilteredMap, entryPredicate)

在每个方法中,我们传递原始地图和一个Predicate,该Predicate与要在子地图中填充的键、条目匹配。

Map<Integer, String> hashmap = new HashMap<>();
hashmap.put(1, "Value1");
hashmap.put(2, "Value2");
hashmap.put(3, "Value3");

List<Integer> keysList = Arrays.asList(1, 2);

Map<Integer, String> subMap = Maps.filterKeys(hashmap, Predicates.in(keysList));

System.out.print(subMap);  //{1=Value1, 2=Value2}

5.总结

在这个Java教程中,我们学会了使用不同的技术从指定的Map中获取子图,这些技术包括Map APIs和Stream API以及Guavafilter()方法。为了得到一个独立于原始地图的子地图,我们必须对地图条目进行迭代,并从选定的条目中创建一个新的地图