【问题标题】:Filtering with Java 8: Map<String, Set<Object>> from Map<String, Set<Object>> based on an attribute of Object使用 Java 8 过滤:基于 Object 属性的 Map<String, Set<Object>> from Map<String, Set<Object>>
【发布时间】:2018-02-09 04:02:38
【问题描述】:

这是类项目。

public class Item {
    String id;
    String name;
    Integer value;
    Boolean status;
}

我有一个地图(字符串,集合(项目))。我想编写一个返回 Map(String, Set(Item)) 的方法,使得结果映射中只存在 status = false 或 status = null 的 Items。我不想要一个集合范围的操作。我希望生成的子集仅包含那些状态 == Boolean.FALSE 或状态 == null 的项目。我不希望整个集合被包含或排除。我只希望根据状态值包含或排除那些单独的项目。

这是我迄今为止尝试过的。

public Map<String,Set<Item>> filterByStatus(Map<String, Set<Item>> changes) {
    return changes.entrySet()
                  .stream()
                  .filter(p -> p.getValue()
                                .stream()
                                .anyMatch(item -> BooleanUtils.isNotTrue(item.isStatus())))
                  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

没用!如果我不调用 filterByStatus,我会得到相同的结果。

更新

public Map<String,Set<Item>> filterByStatus(Map<String, Set<Item>> changes) {
    return changes.entrySet()
                  .stream()
                  .map(p -> p.getValue()
                                .stream()
                                .filter(item -> BooleanUtils.isNotTrue(item.isStatus())))
                  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

结果:collect(Collectors.toMap()) 行中出现错误,指出无法从静态上下文引用非静态方法。

【问题讨论】:

  • 在您的代码中,pSet&lt;Item&gt;anyMatch() 表示如果整个集合中有任何一个为假,则整个集合都会被包含在内。
  • 哦,我根本不想要那个。所以,我想要的是在 Set 中有任何那些具有 status == Boolean.FALSE 或 status == null 的项目。我不希望整个集合被包含或排除。我只希望根据状态值包含或排除那些单独的项目。状态是一个布尔值。让我更新问题以包含这些详细信息。
  • 谢谢赛拉斯。从p中,如何在保留Set的同时根据条件过滤掉所有Item?我会用我尝试做的事情来更新问题。

标签: java java-8 hashmap java-stream


【解决方案1】:
public Map<String, Set<Item>> filterByStatus(Map<String, Set<Item>> changes) {
    return changes.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, entry ->
                entry.getValue()
                    .stream()
                    .filter(item -> item.status == null || item.status == Boolean.FALSE)
                    .collect(Collectors.toSet())
            ));
}

【讨论】:

  • .filter(item -&gt; !Boolean.TRUE.equals(item.status))
【解决方案2】:

作为 Stream 解决方案的替代方案,您可以使用

public Map<String, Set<Item>> filterByStatus(Map<String, Set<Item>> changes) {
    Map<String, Set<Item>> result = new HashMap<>(changes);
    result.replaceAll((key, set) -> {
        set = new HashSet<>(set);
        set.removeIf(item -> Boolean.TRUE.equals(item.status));
        return set;
    });
    // if you want to remove empty sets afterwards:
    result.values().removeIf(Set::isEmpty);
    return result;
}

如果集合是可变的并且您不再需要旧状态,您甚至可以就地执行操作:

changes.values().forEach(set -> set.removeIf(item -> Boolean.TRUE.equals(item.status)));
// if you want to remove empty sets afterwards (and the map is mutable):
changes.values().removeIf(Set::isEmpty);

您甚至可以删除这些项目,然后仅当它们因删除而变为空时才删除该集合,在一个语句中:

changes.values().removeIf(set ->
    set.removeIf(item -> Boolean.TRUE.equals(item.status)) && set.isEmpty());

【讨论】:

    【解决方案3】:

    从您的描述来看,您正在寻找allMatch,而不是anyMatch

    目前你得到了所有包含至少一个非真值的集合。您似乎想要的只是仅包含非 True 值的集合。

    如果您希望过滤掉所有集合中的负值,您应该在 Map 上使用映射,而不仅仅是过滤器。在映射中,您可以创建排除 True 值的集合的副本。

    【讨论】:

      【解决方案4】:

      这避免包含在具有 0 个项目的新地图条目中。

      private Map<String,Set<Item>> filterByStatus(Map<String, Set<Item>> changes) {
          return changes.entrySet()
                  .stream()
                  .filter(entry -> entry.getValue()
                          .stream()
                          .anyMatch(item -> item.status == null || item.status == false))
                  .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
                          .stream()
                          .filter(item -> item.status == null || item.status == false)
                          .collect(Collectors.toSet()))
                  );
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-03
        • 2018-09-22
        • 2015-07-26
        • 2022-01-17
        • 1970-01-01
        相关资源
        最近更新 更多