Java8:使用过滤器/谓词以及析取

时间:2018-03-18 02:15:40

标签: collections java-8 predicate

有两个结构相同的地图说map1和map2的结构为Map<String, Boolean>

地图1包含以下项目:
("i1", True),("i2", True), ("i3", False), ("i4", True)
地图2包含以下项目:
("i1", True),("i2", False), ("i3", True), ("i5", True)

我想要两种信息:
Information1: map1TrueMoreThanMap2True = 2
map1TrueMoreThanMap2True为2,因为我们正在比较地图条目 在这种情况下,map1和map2之间的差异是:
Map1 - ("i2", True),("i4", True)

Information2: map1FalseMoreThanMap2False = 1
在这种情况下,map1和map2之间的差异是:
Map1 - ("i3", False)

我通过编写以下代码来实现这一目标:

 Map<String, Boolean> trueCountMap1 = map1.entrySet().stream()
                .filter(p -> p.getValue() == Boolean.TRUE)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        Map<String, Boolean> trueCountMap2 = map2.entrySet().stream()
                .filter(p -> p.getValue() == Boolean.TRUE)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        Map<String, Boolean> falseCountMap1 = map1.entrySet().stream()
                .filter(p -> p.getValue() == Boolean.FALSE)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        Map<String, Boolean> falseCountMap2 = map2.entrySet().stream()
                .filter(p -> p.getValue() == Boolean.FALSE)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        map1TrueMoreThanMap2True = (CollectionUtils.disjunction(trueCountMap1.entrySet(), trueCountMap2.entrySet())
                .size())/2;
        map1FalseMoreThanMap2False = (CollectionUtils
                .disjunction(falseCountMap1.entrySet(), falseCountMap2.entrySet()).size())/2;

我认为上面的代码很冗长。有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以定义一种在内部使用partitioningBy的方法:

static Map<Boolean, Set<Map.Entry<String, Boolean>>> partition(Map<String, Boolean> map){
      return map.entrySet()
                .stream()
                .collect(Collectors.partitioningBy(Map.Entry::getValue, 
                                                   Collectors.toSet()));
}

现在,你可以这样做:

Map<Boolean, Set<Map.Entry<String, Boolean>>> firstResultSet = partition(map1);

Map<Boolean, Set<Map.Entry<String, Boolean>>> secondResultSet = partition(map2);

调用firstResultSet.get(true)将返回一组映射条目,其中每个条目键的对应值为true

相反,调用firstResultSet.get(false)将返回一组映射条目,其中每个条目键的对应值为false

可以对secondResultSet地图进行相同的操作,以便检索相应的地图条目集。

答案 1 :(得分:2)

据我所知,您想知道map1映射到true(分别为false)的条目数与map2的条目不同。通过将析取的大小减半,这不起作用。当所有密钥保证相同时,它会起作用,但在示例数据中,只有"i4"map1中只有"i5"存在map2。看起来像是巧合,两者都映射到相同的值。只要映射到不同的值,您的方法就会失败。

直接实现“ map1映射到true(分别为false)的条目数量与{{1>的条目不同”要简单得多}} “而不是处理集合操作:

map2

如果您愿意,可以在一个Stream操作中执行此操作:

int map1TrueMoreThanMap2True   = (int)map1.entrySet().stream()
    .filter(e ->  e.getValue() && !map2.getOrDefault(e.getKey(), false))
    .count();
int map1FalseMoreThanMap2False = (int)map1.entrySet().stream()
    .filter(e -> !e.getValue() && map2.getOrDefault(e.getKey(), true))
    .count();