Java8:与析取一起使用filters/predicates
Java8: Use filters/predicates along with disjunction
有两个具有相同结构的映射,例如 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;
我认为上面的代码很冗长。有没有更好的方法呢??
您可以定义一个在内部使用 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)
将 return 一组映射条目,其中每个条目键都有对应的值 true
。
反过来调用 firstResultSet.get(false)
将 return 一组映射条目,其中每个条目键都有对应的值 false
。
可以对 secondResultSet
地图执行相同的操作,以检索相应的地图条目集。
据我了解,您想知道 map1
中有多少条目映射到 true
(resp. false
)并且与 [=15 中的条目不同=].将析取的大小减半是行不通的。当保证所有键都相同时它会起作用,但在您的示例数据中,有不同的键,"i4"
仅存在于 map1
中,"i5"
仅存在于 [=15= 中],两者都映射到相同的值,这看起来纯属巧合。一旦映射到不同的值,您的方法就会失败。
straight-forwardly 实现“map1
的多少条目映射到 true
(相应的 false
)并不同于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();
有两个具有相同结构的映射,例如 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;
我认为上面的代码很冗长。有没有更好的方法呢??
您可以定义一个在内部使用 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)
将 return 一组映射条目,其中每个条目键都有对应的值 true
。
反过来调用 firstResultSet.get(false)
将 return 一组映射条目,其中每个条目键都有对应的值 false
。
可以对 secondResultSet
地图执行相同的操作,以检索相应的地图条目集。
据我了解,您想知道 map1
中有多少条目映射到 true
(resp. false
)并且与 [=15 中的条目不同=].将析取的大小减半是行不通的。当保证所有键都相同时它会起作用,但在您的示例数据中,有不同的键,"i4"
仅存在于 map1
中,"i5"
仅存在于 [=15= 中],两者都映射到相同的值,这看起来纯属巧合。一旦映射到不同的值,您的方法就会失败。
straight-forwardly 实现“map1
的多少条目映射到 true
(相应的 false
)并不同于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();