测试两组是否与Java流共享3个元素

zak*_*zak 10 java set java-stream

我需要一个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;
}
Run Code Online (Sandbox Code Playgroud)

我们如何使用Java流操作来做到这一点?

dav*_*xxx 11

您可以简单地使用Set.retainAll(Collection)

setOne.retainAll(setTwo);
boolean isMoreTwo = setOne.size() > 2
Run Code Online (Sandbox Code Playgroud)

如果您不想修改setOne,请创建Set的新实例:

Set<Integer> newSetOne = new HashSet<>(setOne)
newSetOne.retainAll(setTwo);
boolean isMoreTwo = newSetOne.size() > 2
Run Code Online (Sandbox Code Playgroud)

请注意,实际显示的解决您需求的所有方法(在您的问题中,我的答案以及Naman的一种方法)都不是在单元测试中执行断言的正确方法。
如果断言失败,则断言应该产生有用的错误消息。
所以这实际上对您没有帮助,因为布尔值是对还是错,仅此而已:

Assertions.assertEquals(true,testSets(setOne,setTwo));
Run Code Online (Sandbox Code Playgroud)

此外,它也应该写成这样:

Assertions.assertTrue(testSets(setOne,setTwo));
Run Code Online (Sandbox Code Playgroud)

为了满足您的要求,您应该计算集合之间匹配元素的数量,并在达到所需目标后立即停止。

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

这样可以提高性能,这是编写单元测试的正确方法。


Nam*_*man 6

使用Stream.count

private boolean testSets(Set<Integer> setOne, Set<Integer> setTwo) {
    return setOne.stream().filter(setTwo::contains).count() > 2;
}
Run Code Online (Sandbox Code Playgroud)

或添加它,如果在早期发现了两个以上的元素,则避免迭代整个集合,请limit用作:

return setOne.stream().filter(setTwo::contains).limit(3).count() > 2;
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望在没有必要的情况下将“ limit(3)”放在“ filter”之后,以防止流遍历“ setOne”的所有元素。 (2认同)