Collections Java8:使用过滤器/谓词和析取

Collections Java8:使用过滤器/谓词和析取,collections,java-8,predicate,Collections,Java 8,Predicate,有两个具有相同结构的地图,如map1和map2,其结构为Map 地图1包含以下项目: (“i1”,True)、(“i2”,True)、(“i3”,False)、(“i4”,True) 地图2包含以下项目: (“i1”,真)、(“i2”,假)、(“i3”,真)、(“i5”,真) 我想要两种信息: 信息1:map1TrueMoreThanMap2True=2 Map1True大于Map2True是2,因为我们正在比较映射条目。 在这种情况下,map1和map2之间的差异为: Map1-(“i2”,T

有两个具有相同结构的地图,如map1和map2,其结构为
Map

地图1包含以下项目:
(“i1”,True)、(“i2”,True)、(“i3”,False)、(“i4”,True)

地图2包含以下项目:
(“i1”,真)、(“i2”,假)、(“i3”,真)、(“i5”,真)

我想要两种信息:
信息1:map1TrueMoreThanMap2True=2

Map1True大于Map2True是2,因为我们正在比较映射条目。
在这种情况下,map1和map2之间的差异为:
Map1-(“i2”,True)、(“i4”,True)

信息2: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;
Map trueCountMap1=map1.entrySet().stream()
.filter(p->p.getValue()==Boolean.TRUE)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
Map trueCountMap2=map2.entrySet().stream()
.filter(p->p.getValue()==Boolean.TRUE)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
Map falseCountMap1=map1.entrySet().stream()
.filter(p->p.getValue()==Boolean.FALSE)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
Map falseCountMap2=map2.entrySet().stream()
.filter(p->p.getValue()==Boolean.FALSE)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
map1TrueMoreThanMap2True=(CollectionUtils.disconction(trueCountMap1.entrySet(),trueCountMap2.entrySet())
.size())/2;
map1FalseMoreThanMap2False=(CollectionUtils
.析取(falseCountMap1.entrySet(),falseCountMap2.entrySet()).size())/2;

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

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

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()));
}
静态映射分区(映射){
return map.entrySet()
.stream()
.collect(收集器.partitionBy(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);
Map firstResultSet=partition(map1);
Map secondResultSet=分区(map2);
调用
firstResultSet.get(true)
将返回一组映射条目,其中每个条目键的对应值为
true

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


可以对
secondResultSet
map执行同样的操作,以检索对应的map条目集。

据我所知,您想知道
map1
中有多少条目映射到
true
(分别为
false
),并且与
map2
的条目不同。将析取的大小减半是行不通的。当所有键都保证相同时,它会起作用,但在您的示例数据中,有不同的键,
“i4”
仅出现在
map1
中,而
“i5”
仅出现在
map2
中,并且看起来两者都映射到了相同的值。只要其中一个映射到不同的值,您的方法就会失败

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

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();
如果您愿意,可以在一个流操作中执行此操作:

Map<Boolean,Long> result = map1.entrySet().stream()
    .filter(e -> e.getValue() ^ map2.getOrDefault(e.getKey(), !e.getValue()))
    .collect(Collectors.partitioningBy(Map.Entry::getValue, Collectors.counting()));
int map1TrueMoreThanMap2True   = result.get(true).intValue();
int map1FalseMoreThanMap2False = result.get(false).intValue();
Map result=map1.entrySet().stream()
.filter(e->e.getValue()^map2.getOrDefault(e.getKey(),!e.getValue())
.collect(Collectors.partitionby(Map.Entry::getValue,Collectors.counting());
int map1TrueMoreThanMap2True=result.get(true.intValue();
int-map1FalseMoreThanMap2False=result.get(false.intValue();

这与所做的差不多,但更好。我已经多次阅读了您的描述,包括代码示例,但仍然不知道您要做什么。据我所知,第一个析取是
(“i2”,True),(“i4”,True),(“i3”,True),(“i5”,True)
,第二个析取是
(“i3”,False),(“i2”,False)
。在什么基础上,你认为你可以简单地将析取的大小减半?变量名表明您假设这是属于第一个映射的条目数,但这与示例数据完全一致。如果您的
map2
包含
(“i5”,True)
?@holger。。。您在回答中理解和解释的内容绝对正确,但是收集到
集合而不是
集合
就足够了,不需要为分区中的所有条目保持相同的
布尔值
。感谢您的回答。如果你能详细解释你的单流操作,那将非常有帮助。它直截了当地说:“对于映射到
true
(resp.
false
)的
map1
(resp.
false
)的每个
条目,计算它”。它利用
Map.getOrDefault
像处理非匹配值一样处理缺少的值。第二个变量的过滤器在
map1
中不需要特定的值,只是它不同于
map2
(xor运算符
^
基本上类似于
!=
中的
布尔值)。它再次使用
getOrDefault
将缺少的值映射到相反的值。然后将结果分为两个计数,分别为
true
false