Reputation: 328568
In Java 8, you can use a method reference to filter a stream, for example:
Stream<String> s = ...;
long emptyStrings = s.filter(String::isEmpty).count();
Is there a way to create a method reference that is the negation of an existing one, i.e. something like:
long nonEmptyStrings = s.filter(not(String::isEmpty)).count();
I could create the not
method like below but I was wondering if the JDK offered something similar.
static <T> Predicate<T> not(Predicate<T> p) { return o -> !p.test(o); }
Upvotes: 503
Views: 266326
Reputation: 691
In this case, you could use org.apache.commons.lang3.StringUtils
and do
int nonEmptyStrings = s.filter(StringUtils::isNotEmpty).count();
Upvotes: 9
Reputation: 5547
Predicate
has default
methods and
, or
and negate
.
However, String::isEmpty
is not a Predicate
. It could also be Function<String, Boolean>
. Without type inference, there is no way to know its functional interface.
If Java had filterNot
method (hint: it doesn't), there could be a nice implicit inference:
s.filterNot(String::isEmpty).count()
Negation by instance method (as mentioned by @axtavt) involves explicit inference:
s.filter(((Predicate<String>) String::isEmpty).negate()).count()
It is rather unsightly. From code clarity point of view, implicit inference generally looks much better, even if it makes compiler's work a little more complicated.
Moreover, method reference isn't a unique identifier of a method. E.g. String::substring
refers to both methods of the same name. Due to method overloading, it is unclear which method it refers to. This shows there is a lot of ambiguity that needs to be cleared.
Before we continue, look at these examples and figure out what happens (last two use Java 11):
Predicate<String> p1 = /*0*/ s -> s.isEmpty();
Function<String, Boolean> f1 = /*1*/ String::isEmpty;
Object o1 = /*2*/ String::isEmpty;
Object o2 = /*3*/ p1;
Function<String, Boolean> f2 = /*4*/ (Function<String, Boolean>) o2;
Function<String, Boolean> f3 = /*5*/ p1::test;
Predicate<Integer> p2 = /*6*/ s -> s.isEmpty();
Predicate<Integer> p3 = /*7*/ String::isEmpty;
var v1 = /*8*/ Predicate.not(String::isEmpty);
var v2 = /*9*/ Predicate.not(s -> s.isEmpty());
Let's analyze these examples:
The lambda infers all its type information from p1
variable in assignment (=
). That also infers that it's actually String s
, and since String
has instance method named isEmpty
with no arguments and correct output type, it compiles.
The method reference also infers its type information from f1
variable in assignment. That also infers the arguments and their types. There is only one matching method in String.
The method reference fails to infer a functional interface
from o1
, Object
is a class
.
Just a simple (if perhaps silly) down-casting of a Predicate
to Object
o2
.
The right operand of assignment is an expression that attempts to cast a Predicate
that is stored in variable of Object
type, as a Function
f2
. Exception is thrown at runtime.
The method reference refers to an instance method of p1
. Functional interface and arguments of said method are inferred from f3
variable, and there is a match.
Effectively, this is a Function<String, Boolean>
wrapper to a Predicate<String>
.
The lambda infers the functional interface and arguments from p3
. The compiler looks for an instance method called isEmpty
with no arguments in Integer
, but there is no such thing.
The method reference infers functional interface. It also infers Integer
as input argument and Boolean
as result type. This rules out instance methods of String
(that would require first argument to be of type String
rather than Integer
). There is no static method String.isEmpty(Integer)
either, so a compiler error occurs.
By using var
, v1
is still strongly typed at compile time, but the inference in the assignment (=
) goes from right to left this time.
The right operand calls static method not
which has one argument, Predicate<T>
. Method reference can infer input arguments count (1) and return type (boolean
). One such method exists in String
and its input type is String
, so method not
can infer String
for <T>
.
Similarly, v2
is a mere consumer here. However, the lack of type information in the lambda results in compiler error as it's unclear what is the type of s
. Perhaps List<BigDecimal>
?
Now that it's clear how it works, let's revisit Predicate.not
. As others mentioned, it was added in Java 11. If you want a cleaner look, especially if you negate multiple predicates in the same class, you might as well go for static import and have a result like this:
s.filter(not(String::isEmpty))
The static import however has its own downside: Adding another not
method that negates something vaguely similar will result in ambiguity that you will need to resolve for your code to compile. The ambiguity is further aggravated by type erasure.
So, it all comes back to the fan favorite, a lambda negated by !
operator. This allows the lambda to infer its type directly from the filter
method and it doesn't look too bad.
s.filter(s -> !s.isEmpty)
(unless you've developed in some newer language like Scala, Kotlin ...)
Summed up, functional paradigm in Java could look and feel better, so pick your poison.
Upvotes: 100
Reputation: 46460
Since this ranks highest on Google for Kotlin too ("kotlin negate function reference"), I'll post an answer here:
import kotlin.reflect.KFunction1
/**
* Kotlin version of [java.util.function.Predicate.negate] for functional types.
*
* Example:
* ```
* val isX: X -> Boolean = ...
* val isNotX = !isX
* val isNotX = isX.not()
* ```
*/
operator fun <T> ((T) -> Boolean).not(): (T) -> Boolean =
{ !this(it) }
/**
* Kotlin version of [java.util.function.Predicate.negate] for method references.
*
* Example:
* ```
* fun isX(x: X): Boolean = ...
* val isNotX = !::isX
* ```
*/
operator fun <T> KFunction1<T, Boolean>.not(): KFunction1<T, Boolean> =
{ it: T -> !this(it) }::invoke
/**
* Kotlin version of [java.util.function.Predicate.or] for functional types.
*/
infix fun <T> ((T) -> Boolean).or(other: (T) -> Boolean): (T) -> Boolean =
{ this(it) || other(it) }
/**
* Kotlin version of [java.util.function.Predicate.or] for method references.
*/
infix fun <T> KFunction1<T, Boolean>.or(other: KFunction1<T, Boolean>): KFunction1<T, Boolean> =
{ it: T -> this(it) || other(it) }::invoke
/**
* Kotlin version of [java.util.function.Predicate.and] for functional types.
*/
infix fun <T> ((T) -> Boolean).and(other: (T) -> Boolean): (T) -> Boolean =
{ this(it) && other(it) }
/**
* Kotlin version of [java.util.function.Predicate.and] for method references.
*/
infix fun <T> KFunction1<T, Boolean>.and(other: KFunction1<T, Boolean>): KFunction1<T, Boolean> =
{ it: T -> this(it) && other(it) }::invoke
I'm not aware these being in stdlib, maybe they exist in some library already. Hope this helps someone in the future as the syntax was non-trivial to come up with.
Upvotes: -2
Reputation: 141
Tip: to negate a collection.stream().anyMatch(...)
, one can use collection.stream().noneMatch(...)
Upvotes: 2
Reputation: 11739
Predicate.not( … )
java-11 offers a new method Predicate#not
So you can negate the method reference:
Stream<String> s = ...;
long nonEmptyStrings = s.filter(Predicate.not(String::isEmpty)).count();
Upvotes: 463
Reputation: 2690
I'm planning to static import the following to allow for the method reference to be used inline:
public static <T> Predicate<T> not(Predicate<T> t) {
return t.negate();
}
e.g.
Stream<String> s = ...;
long nonEmptyStrings = s.filter(not(String::isEmpty)).count();
Update: Starting from Java-11, the JDK offers a similar solution built-in as well.
Upvotes: 253
Reputation: 11
You can accomplish this as long emptyStrings = s.filter(s->!s.isEmpty()).count();
Upvotes: 1
Reputation: 2010
If you're using Spring Boot (2.0.0+) you can use:
import org.springframework.util.StringUtils;
...
.filter(StringUtils::hasLength)
...
Which does:
return (str != null && !str.isEmpty());
So it will have the required negation effect for isEmpty
Upvotes: 0
Reputation: 13137
There is a way to compose a method reference that is the opposite of a current method reference. See @vlasec's answer below that shows how by explicitly casting the method reference to a Predicate
and then converting it using the negate
function. That is one way among a few other not too troublesome ways to do it.
The opposite of this:
Stream<String> s = ...;
int emptyStrings = s.filter(String::isEmpty).count();
is this:
Stream<String> s = ...;
int notEmptyStrings = s.filter(((Predicate<String>) String::isEmpty).negate()).count()
or this:
Stream<String> s = ...;
int notEmptyStrings = s.filter( it -> !it.isEmpty() ).count();
Personally, I prefer the later technique because I find it clearer to read it -> !it.isEmpty()
than a long verbose explicit cast and then negate.
One could also make a predicate and reuse it:
Predicate<String> notEmpty = (String it) -> !it.isEmpty();
Stream<String> s = ...;
int notEmptyStrings = s.filter(notEmpty).count();
Or, if having a collection or array, just use a for-loop which is simple, has less overhead, and *might be **faster:
int notEmpty = 0;
for(String s : list) if(!s.isEmpty()) notEmpty++;
*If you want to know what is faster, then use JMH http://openjdk.java.net/projects/code-tools/jmh, and avoid hand benchmark code unless it avoids all JVM optimizations — see Java 8: performance of Streams vs Collections
**I am getting flak for suggesting that the for-loop technique is faster. It eliminates a stream creation, it eliminates using another method call (negative function for predicate), and it eliminates a temporary accumulator list/counter. So a few things that are saved by the last construct that might make it faster.
I do think it is simpler and nicer though, even if not faster. If the job calls for a hammer and a nail, don't bring in a chainsaw and glue! I know some of you take issue with that.
wish-list: I would like to see Java Stream
functions evolve a bit now that Java users are more familiar with them. For example, the 'count' method in Stream could accept a Predicate
so that this can be done directly like this:
Stream<String> s = ...;
int notEmptyStrings = s.count(it -> !it.isEmpty());
or
List<String> list = ...;
int notEmptyStrings = lists.count(it -> !it.isEmpty());
Upvotes: 165
Reputation: 1152
You can use Predicates from Eclipse Collections
MutableList<String> strings = Lists.mutable.empty();
int nonEmptyStrings = strings.count(Predicates.not(String::isEmpty));
If you can't change the strings from List
:
List<String> strings = new ArrayList<>();
int nonEmptyStrings = ListAdapter.adapt(strings).count(Predicates.not(String::isEmpty));
If you only need a negation of String.isEmpty()
you can also use StringPredicates.notEmpty()
.
Note: I am a contributor to Eclipse Collections.
Upvotes: 4
Reputation: 290
I have written a complete utility class (inspired by Askar's proposal) that can take Java 8 lambda expression and turn them (if applicable) into any typed standard Java 8 lambda defined in the package java.util.function
. You can for example do:
asPredicate(String::isEmpty).negate()
asBiPredicate(String::equals).negate()
Because there would be numerous ambiguities if all the static methods would be named just as()
, I opted to call the method "as" followed by the returned type. This gives us full control of the lambda interpretation. Below is the first part of the (somewhat large) utility class revealing the pattern used.
Have a look at the complete class here (at gist).
public class FunctionCastUtil {
public static <T, U> BiConsumer<T, U> asBiConsumer(BiConsumer<T, U> biConsumer) {
return biConsumer;
}
public static <T, U, R> BiFunction<T, U, R> asBiFunction(BiFunction<T, U, R> biFunction) {
return biFunction;
}
public static <T> BinaryOperator<T> asBinaryOperator(BinaryOperator<T> binaryOperator) {
return binaryOperator;
}
... and so on...
}
Upvotes: 4
Reputation: 2581
Another option is to utilize lambda casting in non-ambiguous contexts into one class:
public static class Lambdas {
public static <T> Predicate<T> as(Predicate<T> predicate){
return predicate;
}
public static <T> Consumer<T> as(Consumer<T> consumer){
return consumer;
}
public static <T> Supplier<T> as(Supplier<T> supplier){
return supplier;
}
public static <T, R> Function<T, R> as(Function<T, R> function){
return function;
}
}
... and then static import the utility class:
stream.filter(as(String::isEmpty).negate())
Upvotes: 18
Reputation: 7926
Building on other's answers and personal experience:
Predicate<String> blank = String::isEmpty;
content.stream()
.filter(blank.negate())
Upvotes: 52