基于Keys列表获取子HashMap的最佳方法是什么?

are*_*ier 20 java hashmap

我有一个HashMap,我想得到一个新的HashMap,它只包含第一个HashMap中的元素,其中K属于一个特定的List.

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

谢谢

T.G*_*lle 19

使用Java8流,有一个功能(优雅)的解决方案.如果keys是要保留的键列表并且map是源Map.

keys.stream()
    .filter(map::containsKey)
    .collect(Collectors.toMap(Function.identity(), map::get));
Run Code Online (Sandbox Code Playgroud)

完整的例子:

    List<Integer> keys = new ArrayList<>();
    keys.add(2);
    keys.add(3);
    keys.add(42); // this key is not in the map

    Map<Integer, String> map = new HashMap<>();
    map.put(1, "foo");
    map.put(2, "bar");
    map.put(3, "fizz");
    map.put(4, "buz");

    Map<Integer, String> res = keys.stream()
        .filter(map::containsKey)
        .collect(Collectors.toMap(Function.identity(), map::get));

    System.out.println(res.toString());
Run Code Online (Sandbox Code Playgroud)

打印: {2=bar, 3=fizz}

编辑filter为地图中缺少的键添加一个


T.G*_*lle 10

是的,有一个解决方案:

Map<K,V> myMap = ...;
List<K> keysToRetain = ...;
myMap.keySet().retainAll(keysToRetain);
Run Code Online (Sandbox Code Playgroud)

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

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

  • 但是他要求一个*新的*`HashMap`。 (2认同)
  • @KrishPrabakar 因此,只需将原始映射传递给第二个映射的构造函数即可复制原始映射:`Map&lt;K,V&gt; map2 = new HashMap&lt;&gt;( myMap );`。然后调用`map2.retainAll(keysToRetain);` (2认同)

Evg*_*eev 6

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

Map m2 = new HashMap(m1);
m2.keySet().retainAll(keys);
Run Code Online (Sandbox Code Playgroud)


vto*_*tor 5

在番石榴的帮助下。

假设您有一个地图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));
Run Code Online (Sandbox Code Playgroud)

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

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


use*_*259 1

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

看着TreeMap.subMap()

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

  • @OP 还指定了一个 HashMap。你说的是 TreeMap (3认同)