使用Java 8过滤:Map <string,set <object =“”>&gt;来自Map <string,set <object =“”>&gt;基于Object的属性

时间:2018-02-09 04:02:38

标签: java java-8 hashmap java-stream

这是课程项目。

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

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

这是我迄今为止所尝试的内容。

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())行中出现错误,说明无法从静态上下文引用非静态方法。

4 个答案:

答案 0 :(得分:3)

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())
            ));
}

答案 1 :(得分: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());

答案 2 :(得分:0)

根据您的说明,您正在寻找allMatch而不是anyMatch

目前,您获得的所有集合至少包含一个非True值。您似乎想要的只是只包含非True值的集合。

如果您正在寻找过滤掉所有集合中的负值,则应在地图上使用映射,而不仅仅是过滤器。在映射中,您可以创建除去True值的集合的副本。

答案 3 :(得分:0)

这可以避免在新地图中包含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()))
            );
}