Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8050818

Predicate::not - provide an easier way to negate a predicate

    Details

    • Type: Enhancement
    • Status: Resolved
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 8u5
    • Fix Version/s: 11
    • Component/s: core-libs
    • Subcomponent:
    • Resolved In Build:
      b17

      Backports

        Description

        A DESCRIPTION OF THE REQUEST :
        Please add a method to java.util.Predicate similar to the following:

             public static <T> Predicate<T> not(Predicate<T> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> notEmpty = not(String::isEmpty);

        List<String> result = originals.stream().filter(notEmpty).collect(Collections.toList());

        ACTUAL -
        I currently have to write this:

        List<String> result = originals.stream().filter(string -> !string.isEmpty()).collect(Collections.toList());

        or this:

        List<String> result = originals.stream().filter(string -> ((Predicate)String::isEmpty).negate()).collect(Collections.toList());

        or this:

        Predicate<String> isEmpty = String::isEmpty;
        List<String> 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.

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  jlaskey Jim Laskey
                  Reporter:
                  webbuggrp Webbug Group
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  3 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: