Has it been considered to add inverse methods to collections which are in Optional?
Stuart Marks
stuart.marks at oracle.com
Fri Dec 18 05:31:34 UTC 2020
On 12/8/20 5:30 AM, Remi Forax wrote:
>> De: "Dave Franken" <dwfranken at 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
More information about the core-libs-dev
mailing list