user3303411
user3303411

Reputation: 57

How to implement method reference as a predicate?

I am new to java8 and I was trying to understand this piece of code. This is the piece of code:

Stream.of("A", "B", "C").anyMatch(someObj.getStringValue()::equalsIgnoreCase)

someObj.getStringValue() references some object and the getStringValue() returns some String value.

What is the equivalent predicate of the method reference being passed into anyMatch(...)?

My understanding was this would be equivalent to:

Predicate<String> p = new Predicate<String>() {
    @Override
    public boolean test(String t) {
        return someObject.getStringValue().equalsIgnoreCase(t);
    }
}
Stream.of("A", "B", "C").anyMatch(p)

With this I get the error "Local variable someObject defined in an enclosing scope must be final or effectively final." Any explanation on this is appreciated.

Upvotes: 3

Views: 889

Answers (1)

Andreas
Andreas

Reputation: 159175

The someObj.getStringValue() expression is evaluated outside, so equivalent code would be:

final String x = someObject.getStringValue();
Predicate<String> p = new Predicate<String>() {
    @Override
    public boolean test(String t) {
        return x.equalsIgnoreCase(t);
    }
}
Stream.of("A", "B", "C").anyMatch(p)

where the local variable x is "anonymous" too.

Because of this, someObject does not need to be effectively final.

You can verify this behavior for the lambda expression in a debugger, by putting a breakpoint inside getStringValue(). Even though the test() method is called 3 times (because the stream has 3 elements, and assuming no match), the getStringValue() method will only be called once.

Upvotes: 3

Related Questions