How to negate a method reference predicate
Asked Answered
I

14

491

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); }
Indeterminism answered 31/1, 2014 at 19:4 Comment(3)
JDK-8050818 covers the addition of a static Predicate.not(Predicate) method. But that issue is still open so we'll see this at the earliest in Java 12 (if ever).Flaminius
Seems like this answer could be the ultimate solution adapted in JDK/11 as well.Perhaps
I would really like to see a special method reference syntax for this case: s.filter(String::!isEmpty)Casares
U
439

Predicate.not( … )

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();
Upchurch answered 20/7, 2018 at 9:58 Comment(1)
To use not(String::isEmpty) without Predicate import it via import static java.util.function.Predicate.not;Skirt
A
250

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.

Arizona answered 18/3, 2014 at 22:26 Comment(3)
@SaintHill but then you have to write it out, giving the parameter a nameApiece
It is in guava docs.guava-libraries.googlecode.com/git/javadoc/com/google/…Apiece
Updated Guava link: static.javadoc.io/com.google.guava/guava/23.0/com/google/common/…Mauser
G
164

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());
Grossman answered 2/2, 2014 at 4:5 Comment(8)
Why do you say it is a lot faster?Polypeptide
@JoséAndias (1) Is it faster or 'a lot faster'? (2) If so, why? What have you determined?Grossman
I am asking you to elaborate on "a lot faster to run". The questions: (1) Is it faster or 'a lot faster'? (2) If so, why? What have you determined? are better answered by you, the author of the statement. I am not considering it to be faster or slower. Thank youPolypeptide
Then I'll throw this out for your consideration — 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. I'm no sure if it is faster or how much faster, but I assume it is 'a lot' faster. But perhaps 'a lot' is subjective. It is simpler to code the later than making negative predicates and streams to do a straight count. My preference .Grossman
Java can optimize compile-time and runtime. For example if you write static int SIZE = 16 * 1024;, it is evaluated compile-time. If you concatenate multiple strings in a single expression, StringBuilder is used. Anyway, if you want maximum efficiency, try other language, if not, try to write it readable rather than "optimized to the core". Optimize the algoritm, not the function call count.Samite
Right you are. Although I'm not a big fan of the long explicit function cast method. Nevertheless, @Samite is correct.Grossman
negate() seems like an ideal solution. Pity it isn't static like Predicate.negate(String::isEmpty); without the cumbersome casting.Bisectrix
Can we dynamically decide whether to negate the predicate or not ? May be from a boolean parameter passed ?Hymettus
S
99

Predicate has methods and, or and negate.

However, String::isEmpty is not a Predicate, it's just a String -> Boolean lambda and it could still become anything, e.g. Function<String, Boolean>. Type inference is what needs to happen first. The filter method infers type implicitly. But if you negate it before passing it as an argument, it no longer happens. As @axtavt mentioned, explicit inference can be used as an ugly way:

s.filter(((Predicate<String>) String::isEmpty).negate()).count()

There are other ways advised in other answers, with static not method and lambda most likely being the best ideas. This concludes the tl;dr section.


However, if you want some deeper understanding of lambda type inference, I'd like to explain it a bit more to depth, using examples. Look at these and try to figure out what happens:

Object obj1                  = String::isEmpty;
Predicate<String> p1         = s -> s.isEmpty();
Function<String, Boolean> f1 = String::isEmpty;
Object obj2                  = p1;
Function<String, Boolean> f2 = (Function<String, Boolean>) obj2;
Function<String, Boolean> f3 = p1::test;
Predicate<Integer> p2        = s -> s.isEmpty();
Predicate<Integer> p3        = String::isEmpty;
  • obj1 doesn't compile - lambdas need to infer a functional interface (= with one abstract method)
  • p1 and f1 work just fine, each inferring a different type
  • obj2 casts a Predicate to Object - silly but valid
  • f2 fails at runtime - you cannot cast Predicate to Function, it's no longer about inference
  • f3 works - you call the predicate's method test that is defined by its lambda
  • p2 doesn't compile - Integer doesn't have isEmpty method
  • p3 doesn't compile either - there is no String::isEmpty static method with Integer argument
Samite answered 28/5, 2015 at 12:26 Comment(0)
A
52

Building on other's answers and personal experience:

Predicate<String> blank = String::isEmpty;
content.stream()
       .filter(blank.negate())
Amphibolite answered 1/4, 2015 at 21:37 Comment(2)
Interesting – you can't inline the functional :: reference like one might wish(String::isEmpty.negate()), but if you assign to a variable first (or cast to Predicate<String> first), that works. I think lambda w/ ! will be most readable in most cases, but it's helpful to know what can and can't compile.Riesman
@JoshuaGoldberg I explained that in my answer: The method reference is not a Predicate on its own. Here, the casting is done by the variable.Samite
C
18

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())
Chickadee answered 27/5, 2015 at 7:3 Comment(4)
I'm actually surprised this works - but it seems that JDK favours Predicate<T> over Function<T, Boolean>. But you won't get Lambdas to cast anything to Function<T, Boolean>.Samite
It works for String but not for List: Error:(20, 39) java: reference to as is ambiguous both method <T>as(java.util.function.Consumer<T>) in com.strands.sbs.function.Lambdas and method <T,R>as(java.util.function.Function<T,R>) in com.strands.sbs.function.Lambdas matchCowper
Daniel, it might happen if you're trying to use overloaded method :)Chickadee
Now that I understand type inference much better than originally, I understand how it works. Basically, it just finds the only option that works. Looks interesting, I just don't know if there is some better name that doesn't cause boilerplate.Samite
T
11

Shouldn't Predicate#negate be what you are looking for?

Topdrawer answered 31/1, 2014 at 19:14 Comment(8)
You need to get a Predicate first.Bratislava
You have to cast String::isEmpty() to Predicate<String> before - it's very ugly.Yseulte
@Indeterminism Use as Predicate<String> p = (Predicate<String>) String::isEmpty; and p.negate().Bratislava
@SotiriosDelimanolis I know, but that defeats the purpose - I'd rather write s -> !s.isEmpty() in that case!Indeterminism
@assylias: Yes, I believe that's actually the idea; that just writing out the lambda longhand is the intended fallback.Dogtrot
@Indeterminism Predicates might be helpful, if it ends up in the final JDK.Bratislava
@SotiriosDelimanolis Outch - if it's not there any more, then it's been removed... That's my answer I suppose then!Indeterminism
btw. @SotiriosDelimanolis - the explicit typecast is unnecessary.Samite
E
9

In this case u could use the org.apache.commons.lang3.StringUtilsand do

int nonEmptyStrings = s.filter(StringUtils::isNotEmpty).count();
Embed answered 20/10, 2016 at 14:6 Comment(1)
No. The question is how to negate any method reference, and takes String::isEmpty as an example. It's still relevant information if you have this use case, but if it only answers the String use case, then it should not be accepted.Column
B
4

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...
}
Barrada answered 28/1, 2016 at 23:46 Comment(0)
K
4

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.

Kobylak answered 27/3, 2016 at 0:11 Comment(0)
H
2

Tip: to negate a collection.stream().anyMatch(...), one can use collection.stream().noneMatch(...)

Hutch answered 2/6, 2022 at 14:49 Comment(0)
V
1

You can accomplish this as long emptyStrings = s.filter(s->!s.isEmpty()).count();

Viperous answered 28/9, 2018 at 12:29 Comment(0)
S
0

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

Stipulate answered 25/9, 2018 at 10:34 Comment(0)
F
-2

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.

Fiden answered 3/8, 2023 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.