On 12/8/20 5:30 AM, Remi Forax wrote:
De: "Dave Franken" <dwfran...@gmail.com>
Adding methods like notContains or notFilter have been considered several times 
in the past and rejected because it's too many methods with no real gain. I'm 
sure you can dig some old emails on lambda-dev and see the first iteration of 
the Stream API, it was full of convenient methods like that.
I'm sure Stuart or Brian have a template answer for that :)

Well I don't have a template handy but I can explain some of the reasoning. :-)

In general we try to avoid adding to many pure "convenience" methods that do things that are easily expressed other ways, e.g., through composition of existing methods or Java language constructs.

There are many boolean-returning methods in the JDK and we've tried to avoid defining methods that are simply inverses of each other. The notable exceptions are Objects.isNull and Objects.nonNull, which seemed sensible at the time, since references being null or non-null is quite fundamental to Java programming. (Note that these are mostly useful only as method references.)

Optional was introduced with isPresent, but without an inverse. Since Optional is (mostly) about having or not-having something, we later somewhat reluctantly added isEmpty, on the basis that the empty/present state of an Optional is as fundamental as null/non-null references.

Another common place where inverse methods have been requested is String. We've held off doing that. String has isEmpty and isBlank, which have different semantics, so this would naturally lead to having nonEmpty and nonBlank. There are also several other boolean-returning methods on String, so you can start to see how this could lead toward excessive method proliferation.

It would improve readability where we have the negation of isEmpty(), e.g.:

if (!myList.isEmpty()) {
}

You might or might not like this syntax, but if you don't, adding new APIs here and there won't really solve anything.

Personally I think adding a space after ! makes the negation stand out a bit more (and I'm used to this) so it doesn't bother me:

    if (! myList.isEmpty()) { ...

One place where negation of a predicate does have a fairly high cost is with method references. If I have a stream where I want to filter for empty collections I could write

    filter(Collection::isEmpty)

which is fairly nice, but if I want to filter for non-empty collections, I have to convert it to a lambda:

    filter(collection -> ! collection.isEmpty())

This is mitigated by the addition of a Predicate.not method, which when statically imported, allows rewriting thus:

    filter(not(Collection::isEmpty))

This enables using method references in a bunch of places where they couldn't be used before, relieving us of the need think of a name for the lambda parameter. In particular, this can be used with the above-mentioned String::isBlank and String::isEmpty. The main point is that Predicate.not can be used with *any* predicate, which lets us avoid adding inverse methods in a bunch of different places.

s'marks

Reply via email to