Count elements in a collection based on a condition [Java 8] Came across this question here: Write a generic method to count the number of elements in a collection that have a specific property (for example, odd integers, prime numbers, palindromes).

Following is my solution:

Counter.java

public class Counter {
    public static &lt;T&gt; long countIf(Collection&lt;T&gt; collection, Predicate&lt;T&gt; predicate) {
        return collection.stream()
                         .filter(predicate)
                         .count();
    }
}


Behaviours.java

public class Behaviours {

    public static boolean checkEvenNumber(final int num) {
        return num % 2 == 0;
    }

    public static boolean checkOddNumber(final int num) {
        return num % 2 != 0;
    }

    public static boolean checkPrimeNumber(final int num) {
        if (num == 0 || num == 1) {
            return false;
        }

        for (int i = 2; i * i &lt;= num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    public static boolean checkPalindrome(final String word) {
        for (int i = 0; i &lt; word.length() / 2; i++) {
            if (word.charAt(i) != word.charAt(word.length() - 1 - i)) {
                return false;
            }
        }
        return true;
    }
}


CounterTest.java

public class CounterTest {

    /**
     * Counting odd numbers.
     */
    @Test
    public void testCountingOddNumbers() {
        System.out.println("testCountingOddNumbers");
        List&lt;Integer&gt; ci = Arrays.asList(1, 2, 3, 4, 5, 6);
        long expected = 3l;
        long actual = Counter.countIf(ci, Behaviours::checkOddNumber);
        Assert.assertEquals(expected, actual);
    }

    /**
     * Counting prime numbers.
     */
    @Test
    public void testCountingPrimeNumbers() {
        System.out.println("testCountingPrimeNumbers");
        List&lt;Integer&gt; ci = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        long expected = 4l;
        long actual = Counter.countIf(ci, Behaviours::checkPrimeNumber);
        Assert.assertEquals(expected, actual);
    }    

    /**
     * Counting palindromes
     */
    @Test
    public void testCountingPalindromes() {
        System.out.println("testCountingPalindromes");
        List&lt;String&gt; cs = Arrays.asList("madam", "test", "tacocat", "hello");
        long expected = 2l;
        long actual = Counter.countIf(cs, Behaviours::checkPalindrome);
        Assert.assertEquals(expected, actual);
    }

}


Output

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mycompany.demo.assignment001.question001.CounterTest
testCountingPalindromes
testCountingPrimeNumbers
testCountingOddNumbers
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.088 sec



Does my implementation take care of all the scenarios or am I missing something?
Can any other Java 8 concept be used here?
Please also review overall correctness.
The code looks very nice! However, here my small complaints:
Tests
The tests are good, but you're testing the Behaviours implicitly, when you test the Counter. The Counter itself does only the following things: stream, filter with the given predicate, and count. The static methods im Behaviours should be tested separately, as should the logic of the Counter. The problem is, if the test fails, you don't know if the problem is the Counter or the Behaviours. The more &quot;implicit&quot; things you test, the harder is it to find the bug.
You're testing with too many values. The logic itself should be the same with two values (one is a palindrome, one is not) as with four values (two palindromes, two not). If the behaviour for two or four values is different, then it's two different test cases.
The lists to count/filter can have a better name.
To make a test case more readable, it's usually split in the three blocks given/when/then, separated by an empty line. Setup the test data / perform the action / assertion.
Also, I recommend, but that's personal preference, to static import static methods, at least the assertion methods, so it looks a bit more clean.
What's missing (at least what I couldn't find):

You're missing the test for even numbers.
You're missing the test for 0/1 number in testCountingPrimeNumbers.
What happens for an empty String (or string with length 1 or 2) in the palindrome count?

Other

check-prefix: The convention is to use a is prefix, if a method returns a boolean, it's more clear than &quot;check&quot;.
test-prefix in test methods: That was the convention for JUnit3 (I think), when annotations weren't a thing. It's not needed anymore, when you use the @Test annotation, so instead of testCountingPrimeNumbers, you can go with countPrimeNumbers.
The JavaDocs for the test methods are obsolete, the method names are clear.
I'd get rid of the System.outs, too, you get enough information in the junit test report.
Instead of naming stuff actual, I'd give it the proper name, e.g. amountOfPalindromes. And maybe not declare the expected variable.

Hope this helps...