在Java 8中,你可以使用方法引用来过滤流,例如:

Stream<String> s = ...;
long emptyStrings = s.filter(String::isEmpty).count();

是否有一种方法可以创建一个方法引用,它是现有方法引用的否定,例如:

long nonEmptyStrings = s.filter(not(String::isEmpty)).count();

我可以创建如下所示的not方法,但我想知道JDK是否提供了类似的东西。

static <T> Predicate<T> not(Predicate<T> p) { return o -> !p.test(o); }

当前回答

您可以使用Eclipse集合中的谓词

MutableList<String> strings = Lists.mutable.empty();
int nonEmptyStrings = strings.count(Predicates.not(String::isEmpty));

如果你不能改变List中的字符串:

List<String> strings = new ArrayList<>();
int nonEmptyStrings = ListAdapter.adapt(strings).count(Predicates.not(String::isEmpty));

如果你只需要String.isEmpty()的否定,你也可以使用StringPredicates.notEmpty()。

注意:我是Eclipse Collections的贡献者。

其他回答

我已经编写了一个完整的实用程序类(受到Askar的建议的启发),它可以接受Java 8 lambda表达式,并将它们(如果适用)转换为包Java .util.function中定义的任何类型的标准Java 8 lambda。你可以这样做:

asPredicate(String::isEmpty).negate() asBiPredicate(String::equals).negate()

因为如果所有静态方法都以as()命名,将会产生许多歧义,所以我选择调用方法“as”,后面跟着返回的类型。这使我们能够完全控制lambda解释。下面是实用工具类的第一部分(有点大),揭示了所使用的模式。

在这里查看完整的课程(要点)。

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...
}

另一种选择是在明确的上下文中使用lambda强制转换为一个类:

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;
    }

}

... 然后静态导入实用程序类:

stream.filter(as(String::isEmpty).negate())

我计划静态导入以下内容,以允许方法引用内联使用:

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();

更新:从Java-11开始,JDK也提供了一个内置的类似解决方案。

如果你正在使用Spring Boot(2.0.0+),你可以使用:

import org.springframework.util.StringUtils;

...
.filter(StringUtils::hasLength)
...

这是: 返回(str != null && !str. isempty ());

因此它将具有isEmpty所需的否定效果

根据别人的回答和个人经验:

Predicate<String> blank = String::isEmpty;
content.stream()
       .filter(blank.negate())