javajava-streamcomparatorpredicateapache-commons-collection

Java 8 Stream filter with comparator


I want to filter list of MyObject based on values field. In this case: if any value on MyObject::getValues is less than given value, than the predicate is false. I haven't found the way to do it with Stream API, so I tried ComparatorPredicate by Apache. Here is my try:

private Predicate<MyObject> valueGreaterThanOrEqualTo(ValueObject value){
    return myObject -> myObject.getValues().stream()
            .noneMatch(v -> ComparatorPredicate.comparatorPredicate(value, new ValueComparator(), ComparatorPredicate.Criterion.LESS)
                    .evaluate(v));
}

This, however, results in:

Caused by: java.lang.ClassCastException: Cannot cast java.lang.Boolean to com.ValueObject
    at java.lang.Class.cast(Class.java:3369)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1351)
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.noneMatch(ReferencePipeline.java:459)

So my question is why does the ClassCastException occur and how to resolve it AND/OR how to resolve my problem with some other (better?) solution?

UPDATE:

A little update on the issue. The first problem (ClassCastException) was caused by the code I didn't include in my example. After solving it ComparatorPredicate works fine, so if you like it: go for it. I, however will go with the suggestion from accepted answer which is simpler and doesn't involve using external libs. Especially since ComparatorPredicate doesn't extend java.util.function.Predicate but org.apache.commons.collections4.Predicate instead.


Solution

  • I don't see why you had to use ComparatorPredicate.comparatorPredicate.

    How about:

    private Predicate<MyObject> valueGreaterThanOrEqualTo(ValueObject value){
        ValueComparator comparator = new ValueComparator();
        return myObject -> myObject.getValues().stream()
                .noneMatch(v -> comparator.compare(v,value)<0);
    }
    

    This is assuming ValueComparator implements Comparator<ValueObject>.