如何很好地将两个地图的两个集合相交?

Gho*_*ica 4 java dictionary set java-8 java-stream

我们的对象具有“属性”;它们的当前状态表示为Map<String, Object>键类似于属性名称的位置。这些值可以具有不同的类型,尽管我当前的任务只是处理布尔属性。

除了当前状态外,还通过此类映射组织对对象的“更新”。

现在,我必须防止当前true被禁用的属性(变成false)。

使用流,这在这里起作用:

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);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码首先获取一组所有的属性true,然后分别收集将要打开的所有属性false。如果这两个集合的交集为空,则表示我很好,否则出错。

上面的方法有效,但是我觉得它很笨拙,并且我不喜欢该currentlyEnabled集合被误用于计算相交的事实。

有什么建议可以用一种更加惯用但可读的“流式”方式来做到这一点吗?

Lin*_*ica 7

您只需选择所有值为的键-值对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 ...
Run Code Online (Sandbox Code Playgroud)

  • 为了提高效率,您可以检查哪个映射较小,并且在较小的映射上进行迭代,即,如果“ updatedObjectPropertiesMap”较小,请使用“ Set &lt;String&gt; matches = updatedObjectPropertiesMap.entrySet()。stream()。filter(e-&gt; Boolean)” .FALSE.equals(e.getValue())).map(Map.Entry :: getKey).filter(k-&gt; Boolean.TRUE.equals(currentObjectPropertiesMap.get(k))).collect(Collectors.toSet() );`相反;结果将是相同的。 (2认同)