【问题标题】:java 8 - is there a good way to filter and remove from a map?java 8 - 有没有一种从地图中过滤和删除的好方法?
【发布时间】:2015-10-12 05:16:22
【问题描述】:

我想从地图中过滤几个对象,如下所示:

  • 使用过滤后的结果创建新地图
  • 从原始地图中删除

目前我用两种方法来做

Map<String, MyObject > map = scenarioFieldsMap.entrySet().stream()
            .filter(e -> e.getKey().contains("["))
            .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()));

scenarioFieldsMap.entrySet().removeIf(e -> e.getKey().contains("["));

有没有更好的过滤和去除方法?

【问题讨论】:

  • 如果在您的手术后它们都相同,为什么还需要两张地图?如果您想要两个不同的实例,您可以从原始地图中删除元素,然后使用复制构造函数。
  • map.keySet().removeIf(k -&gt; k.contains("["));
  • @AlexisC。他们不会是一样的。 OP 希望从原始地图中删除一些条目,新地图应包含所有已删除的条目。
  • @Eran 是的,但是代码并没有反映这一点。我猜 OP 的意思是 scenarioFieldsMap.entrySet().removeIf(e -&gt; e.getKey().contains("["));
  • @AlexisC.是的,这一定是一个错字。否则,OP 将以一个空映射结束(在第二步中删除了在第一步中添加的所有条目之后)。

标签: java java-8 java-stream


【解决方案1】:

您也可以使用partitioningBy 收集器:

Collector<Entry<String, MyObject>, ?, Map<Boolean, Map<String, MyObject>>> collector = 
    Collectors.partitioningBy(e -> e.getKey().contains("["),
                Collectors.toMap(Entry::getKey, Entry::getValue));
Map<Boolean, Map<String, MyObject>> maps = scenarioFieldsMap.entrySet()
        .stream().collect(collector);

这样您不会修改原始映射,而是创建两个新映射:maps.get(true) 是键包含 "[" 的映射,maps.get(false) 包含其余所有映射。

【讨论】:

    【解决方案2】:

    如果不是遍历所有键(或条目),而只删除另一个映射中存在的键,则第二步会更有效:

    scenarioFieldsMap.keySet().removeAll(map.keySet());
    

    我假设您打算从原始 scenarioFieldsMap 中删除条目,而不是从您在第一步中创建的新地图中删除。

    【讨论】:

    • 谢谢。确切地。我可以只迭代一次scenarioFieldsMap - 删除和创建新集合吗?还是我要通过两次迭代来完成?
    • @rails 我想不出一种方法来使用 Streams 在一次迭代中创建新地图并从旧地图中删除。但是,如果您按照我的建议更改第二步,它只会遍历必须删除的键(因为可以在预期的恒定时间内访问它们中的每一个),并且不必再次运行过滤。
    猜你喜欢
    • 1970-01-01
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    相关资源
    最近更新 更多