我需要Java流操作来测试两组是否至少具有3个公共元素。
这是我的Java 7代码,可以正常工作:
@Test
public void testContainement(){
Set<Integer> setOne = IntStream.of(0,1,4,3)
.boxed()
.collect(Collectors.toCollection(HashSet::new));
Set<Integer> setTwo = IntStream.of(0,1,4,5)
.boxed()
.collect(Collectors.toCollection(HashSet::new));
Assertions.assertEquals(true,testSets(setOne,setTwo));
}
private boolean testSets( Set<Integer> setOne, Set<Integer> setTwo ) {
int counter=0;
for (int x: setOne){
if (setTwo.contains(x))
counter++;
}
return counter > 2;
}
如何用Java流操作做到这一点?
答案 0 :(得分:11)
您可以简单地使用Set.retainAll(Collection)
:
setOne.retainAll(setTwo);
boolean isMoreTwo = setOne.size() > 2
如果您不想修改setOne
,请创建Set的新实例:
Set<Integer> newSetOne = new HashSet<>(setOne)
newSetOne.retainAll(setTwo);
boolean isMoreTwo = newSetOne.size() > 2
请注意,实际显示的解决您需求的所有方法(在您的问题中,我的答案以及Naman的一种方法)都不是在单元测试中执行断言的正确方法。
如果断言失败,则断言应该产生有用的错误消息。
因此,这对您毫无帮助,因为布尔值是对还是错,仅此而已:
Assertions.assertEquals(true,testSets(setOne,setTwo));
此外,它的写法也应类似于:
Assertions.assertTrue(testSets(setOne,setTwo));
要满足您的要求,您应该计算集合之间匹配元素的数量,并在达到所需目标后立即停止。
long nbMatchLimitedToThree = setOne.stream().filter(setTwo::contains).limit(3).count();
Assertions.assertEqual(3, nbMatchLimitedToThree, "At least 3 matches expected but actually only " + nbMatchLimitedToThree +". setOne=" + setOne + ",setTwo=" + setTwo);
性能更高,这是编写单元测试的正确方法。
答案 1 :(得分:6)
使用Stream.count
作为
private boolean testSets(Set<Integer> setOne, Set<Integer> setTwo) {
return setOne.stream().filter(setTwo::contains).count() > 2;
}
或添加到其中,如果在早期发现了两个以上的元素,则避免遍历整个集合,请使用limit
作为
return setOne.stream().filter(setTwo::contains).limit(3).count() > 2;
答案 2 :(得分:2)
番石榴很容易阅读:
private boolean testSets( Set<Integer> setOne, Set<Integer> setTwo ) {
return Sets.intersection(setOne, setTwo).size() > 2;
}