I need a Java stream operation to test if two sets have at least 3 common elements.
Here is my Java 7 code that works fine:
@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;
}
How can we do that with Java stream operations?
Java Stream anyMatch () Examples Example 1: Java program to check if stream contains a specific element In this Java example, we are using the anyMatch () method to check if the stream contains the string "four". As we see that the stream contains the string, so the output of the example is true.
We often need to compare two sets to check whether they contain the same elements or not, and both sets should also have the same size. The Set interface provides the equals () method for verifying the equality of the given two sets. It returns either true or false based on the equality of both sets.
Stream.concat () method creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. import java.util.stream.*; Set a: [1, 3, 5, 7, 9] Set b: [0, 2, 4, 6, 8] Merged Set: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
You can use predicate or () or isEquals () methods with the multiple predicate conditions. 4. Conclusion You learned how to use the filter () method and the predicate and () method to add multiple conditions to stream objects in this article.
You could use simply Set.retainAll(Collection)
:
setOne.retainAll(setTwo);
boolean isMoreTwo = setOne.size() > 2
If you don't want to modify setOne
, create a new instance of the Set :
Set<Integer> newSetOne = new HashSet<>(setOne)
newSetOne.retainAll(setTwo);
boolean isMoreTwo = newSetOne.size() > 2
Note that all ways actually shown to solve your need (in your question, my answer and that one of Naman) are not correct way to perform an assertion in an unit test.
An assertion should produce a useful error message if the assertion fails.
So that will really not help you since a boolean is true or false and that's all :
Assertions.assertEquals(true,testSets(setOne,setTwo));
Besides, it should also be written rather like :
Assertions.assertTrue(testSets(setOne,setTwo));
To achieve your requirement, you should count the number of matching elements between the sets and stopping it as soon as you reach the desired target.
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);
That is more performant and that is a correct way to write unit tests.
Use Stream.count
as
private boolean testSets(Set<Integer> setOne, Set<Integer> setTwo) {
return setOne.stream().filter(setTwo::contains).count() > 2;
}
or to add to it, avoiding to iterate through the complete set if more than two elements are found early, use limit
as:
return setOne.stream().filter(setTwo::contains).limit(3).count() > 2;
guava makes this very easy to read:
private boolean testSets( Set<Integer> setOne, Set<Integer> setTwo ) {
return Sets.intersection(setOne, setTwo).size() > 2;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With