Java 如何从两张地图上很好地相交两个集合?

Java 如何从两张地图上很好地相交两个集合?,java,dictionary,java-8,set,java-stream,Java,Dictionary,Java 8,Set,Java Stream,我们的对象有“属性”;它们的当前状态表示为Map,其中键类似于属性的名称。这些值可以有不同的类型,但我当前的任务只是处理布尔属性 除当前状态外,还通过此类地图组织对象的“更新” 现在我必须防止当前为true的属性被禁用(变为false) 使用streams,这里的工作原理如下: Set<String> currentlyEnabled = currentObjectPropertiesMap. .entrySet() .stream()

我们的对象有“属性”;它们的当前状态表示为
Map
,其中键类似于属性的名称。这些值可以有不同的类型,但我当前的任务只是处理布尔属性

除当前状态外,还通过此类地图组织对象的“更新”

现在我必须防止当前为
true
的属性被禁用(变为
false

使用streams,这里的工作原理如下:

Set<String> currentlyEnabled = currentObjectPropertiesMap.
            .entrySet()
            .stream()
            .filter(e -> Boolean.TRUE.equals(e.getValue()))
            .map(Entry::getKey)
            .collect(Collectors.toSet());

Set<String> goingDisabled = updatedObjectPropertiesMap
        .entrySet()
        .stream()
        .filter(e -> Boolean.FALSE.equals(e.getValue()))
        .map(Entry::getKey)
        .collect(Collectors.toSet());

currentlyEnabled.retainAll(goingDisabled);

if (currentlyEnabled.isEmpty()) {
    return;
} else {
  throw new SomeExceptionThatKnowsAllBadProperties(currentlyEnabled);
}
设置currentlyEnabled=currentObjectPropertiesMap。
.entrySet()
.stream()
.filter(e->Boolean.TRUE.equals(e.getValue()))
.map(条目::getKey)
.collect(收集器.toSet());
Set goingDisabled=updateObjectPropertiesMap
.entrySet()
.stream()
.filter(e->Boolean.FALSE.equals(e.getValue()))
.map(条目::getKey)
.collect(收集器.toSet());
当前启用。保留(goingDisabled);
如果(currentlyEnabled.isEmpty()){
返回;
}否则{
抛出新的SomeExceptionAtKnowsAllBadProperties(currentlyEnabled);
}
上面的代码首先获取一组
true
的所有属性,然后分别收集将变为
false
的所有属性。如果这两个集合的交集是空的,我很好,否则会出错

上面的方法很有效,但我觉得它很笨拙,而且我不喜欢
currentlydenabled
集合被误用来计算交点


有没有什么建议可以用一种更惯用、但可读性更高的“流式”方式来实现这一点

您只需选择值为
true
的所有键值对,然后通过键检查“更新”-映射中的值是否为
false

Set<String> matches = currentObjectPropertiesMap
    .entrySet()
    .stream()
    .filter(e -> Boolean.TRUE.equals(e.getValue()))
    .map(Map.Entry::getKey)
    .filter(k -> Boolean.FALSE.equals(
        updatedObjectPropertiesMap.get(k)
    ))
    .collect(Collectors.toSet());

if(!matches.isEmpty()) throw ...
Set matches=currentObjectPropertiesMap
.entrySet()
.stream()
.filter(e->Boolean.TRUE.equals(e.getValue()))
.map(map.Entry::getKey)
.filter(k->Boolean.FALSE.equals(
UpdateObjectPropertiesMap.get(k)
))
.collect(收集器.toSet());
如果(!matches.isEmpty())抛出。。。
一个不包含显式集合交点的解决方案可以是:

Set<String> violatingProperties = new HashSet<String>();
for (Entry<String, Object> entry : currentObjectPropertiesMap.entrySet()) {
    if (! (Boolean) entry.getValue()) {
        continue;
    }
    if (! updatedObjectPropertiesMap.hasKey(entry.getKey())) {
        continue;
    }
    if (! (Boolean) updatedObjectPropertiesMap.get(entry.getKey())) {
        violatingProperties.add(entry.getKey());
    }
}
if (violatingProperties.size() > 0) {
    throw ...
}
Set violatingProperties=new HashSet();
对于(条目:currentObjectPropertiesMap.entrySet()){
if(!(布尔)entry.getValue(){
继续;
}
如果(!updateObjectPropertiesMap.hasKey(entry.getKey())){
继续;
}
如果(!(布尔)UpdateObjectPropertiesMap.get(entry.getKey())){
violatingProperties.add(entry.getKey());
}
}
如果(violatingProperties.size()>0){
扔。。。
}

尝试
anyMatch

boolean anyMatch = currentXXXMap.entrySet()
    .stream()
    .anyMatch(e -> e.getValue() && !updatedXXXMap.getOrDefault(e.getKey(), true));

为什么不迭代
currentObjectPropertiesMap.entrySet()
对值为
false
的条目继续执行
,否则,检查
是否更新了对象属性Map.hasKey()
,是否为真,然后,如果该键的值为
false
,则引发异常?问题是我A)更喜欢流解决方案,B)我需要“收集”所有违反我条件的属性名称。更新代码以保存违反条件的属性名称可以将两个
过滤器
合并为一个,然后映射
。虽然没有太大的区别
.filter(e->Boolean.TRUE.equals(e.getValue())&&Boolean.FALSE.equals(updateobjectpropertiesmap.get(e.getKey())).map(map.Entry::getKey)
@Naman我同意,但在我看来,流语句应该尽可能简单。我的经验法则是每个
过滤器
/
映射
-操作(如果可能)有一个条件/语句,但正如前面所说的,这只是一个关于效率的观点,您可以检查哪个映射更小,然后在较小的映射上迭代,即如果
updateObjectPropertiesMap
更小,使用
Set matches=updateObjectPropertiesMap.entrySet().stream().filter(e->Boolean.FALSE.equals(e.getValue()).map(map.Entry::getKey).filter(k->Boolean.TRUE.equals(currentObjectPropertiesMap.get(k)).collect(Collector.toSet())取而代之;结果是一样的。