Loading... (original) (raw)
A DESCRIPTION OF THE REQUEST :
Please add a method to java.util.Predicate similar to the following:
public static Predicate not(Predicate target) {
return target.negate();
}
JUSTIFICATION :
There is currently no easy way to negate a predicate which is a lambda (as opposed to an actual Predicate object).
Suppose I want to create a list of empty strings using the Stream API. It is easy:
List result = originals.stream().filter(String::isEmpty).collect(Collections.toList());
However, if I instead want to create a list of nonempty strings, I have to do a bit more work. Suddenly, I am forced to introduce a named variable and do an explicit method call:
List result = originals.stream().filter(string -> !string.isEmpty()).collect(Collections.toList());
I can't use a method reference here because there is no method in the String class for determining if a string is not empty. (I wish there were!)
In principle, the Predicate.negate() method is intended to be used in these sorts of situations, but in this case it can't be, because String::isEmpty is not a Predicate until and unless it is assigned to one, so I would have to create a temporary Predicate object (or use a cast) to get a Predicate to call negate() on.
I would like to be able to easily create a negated version of a lambda, like this:
import static java.util.function.Predicate.not;
List result = originals.stream().filter(not(String::isEmpty)).collect(Collections.toList());
Also see discussion here:
http://stackoverflow.com/questions/21488056/how-to-negate-a-method-reference-predicate
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would like to be able to write this:
import static java.util.function.Predicate.not;
List result = originals.stream().filter(not(String::isEmpty)).collect(Collections.toList());
or for slightly better performance (assuming the JDK's optimizer fails at noticing that 'not(String::isEmpty)' is a constant expression - I'm not sure if it can handle this), I could write this:
Predicate notEmpty = not(String::isEmpty);
List result = originals.stream().filter(notEmpty).collect(Collections.toList());
ACTUAL -
I currently have to write this:
List result = originals.stream().filter(string -> !string.isEmpty()).collect(Collections.toList());
or this:
List result = originals.stream().filter(string -> ((Predicate)String::isEmpty).negate()).collect(Collections.toList());
or this:
Predicate isEmpty = String::isEmpty;
List result = originals.stream().filter(isEmpty.negate()).collect(Collections.toList());
all of which are harder to read and unnecessarily different from the equivalent code which uses a direct method reference to the String::isEmpty method.