内置的Java 8谓词总是返回true?

Gar*_*son 116 java lambda predicate java-8

Google Guava有一个始终返回true的谓词.Java 8有类似的东西Predicate吗?我知道我可以使用(foo)->{return true;},但我想要预制的东西,类似于Collections.emptySet().

Stu*_*rks 151

Java 8中没有内置的always-true和always-false谓词.编写这些内容的最简洁方法是

x -> true
Run Code Online (Sandbox Code Playgroud)

x -> false
Run Code Online (Sandbox Code Playgroud)

比较这些

Predicates.alwaysTrue() // Guava
Run Code Online (Sandbox Code Playgroud)

最后到一个匿名的内部类:

new Predicate<Object>() {
    public boolean test(Object x) {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

可能是Guava具有这些内置谓词的原因是静态方法调用对匿名内部类有很大的语法优势.在Java 8中,lambda语法非常简洁,以至于写出静态方法调用存在语法上的缺点.

不过,这只是一种语法比较.如果存在单个全局始终为真的谓词,那么与x -> true跨多个类的出现相比,可能存在一个小的空间优势,每个类都会创建自己的谓词实例.这是你关心的吗?这些节省似乎并不引人注目,这可能就是为什么它们不是首先添加的原因.但可以重新考虑将来的版本.

更新2015-04-24

我们认为加入各种静态,命名等功能Predicate.alwaysTrue,Runnable.noop等等,我们已决定不添加任何更多的在Java SE的未来版本.

当然,有一些名称与写出的lambda有一些价值,但这个值非常小.我们希望人们将学习如何阅读和写作x -> true,() -> { }并且他们的使用将成为惯用语.即使是Function.identity()过去的价值x -> x也值得怀疑.

重用现有函数而不是评估写出的lambda有一个微小的性能优势,但是我们希望这些函数的使用非常小,以至于这样的优势可以忽略不计,当然不值得API膨胀.

Holger在评论中还提到了优化组合函数等的可能性Predicate.or.这也被认为是(JDK-8067971),但被认为有些脆弱且容易出错,并且很少发生,因此不值得付出努力.

另请参阅此Lambda FAQ条目.

  • 规范的`Predicate.alwaysTrue()`和`Predicate.alwaysFalse()`实例的一大优点是,它们可以通过组合诸如`Predicate.or`,`Predicate.and`和`Predicate.negate( )`.这将允许使用`alwaysTrue()`预先初始化`Predicate`变量,并通过在没有开销的情况下组合通过`和`来添加谓词.由于lambda表达式没有对象身份保证,因此可能会因`x-> true`而失败.顺便说一句,如果我有一个带有`static`方法`y(){返回true;}`的类`X`,使用`X :: y`甚至比`x-> true'更短但不是真的推荐... (22认同)
  • 两个问题:第一个是简洁.如果`(foo) - > {return true;}`是我能做的最好的,我想要更好.但是你提出了`x-> true`,它更好,减轻了第一个问题.第二个问题是逻辑与静态声明.如果我使用`x-> true`,仍然存在逻辑,我可能无意中搞砸了(例如`x - >!true`).但是使用`Predicate.alwaysTrue()`,逻辑错误没有空间,因为只有一两种类似的方法.另外,我免费获得IDE代码.`x-> true`几乎没问题,但由于上述原因,我仍然写了一个`Predicate.alwaysTrue()`方法. (12认同)
  • @GarretWilson但是使用`Predicate.alwaysTrue()`你也可能因意外写'Predicate.alwaysFalse()`而搞砸了. (9认同)
  • 成语`x - > true`的缺点是我不得不使用变量.这会在我的IDE中产生不必要的大脑负载和警告.我试图使用`_ - > true`,但这是一个语法错误.Java肯定缺少"unused参数"的关键字(读取:keyletter).希望这样的东西会出现在Java 9中(或至少:Java之前我死的^^) (9认同)
  • @DavidConrad,当然.我总有办法犯错误,事实上我不断发明新的错误.;)我不想在这里开始讨论一些微不足道的事情,但我只想说我的观点是,使用静态方法引用我有一个只有两个选择的约束词汇:`alwaysTrue()`和`alwaysFalse ()`.有了实际的lambda,我有很多变化; 我基本上每次重建公式.从本质上讲,`alwaysTrue()`是我想做的语义标签; `x-> true`实际上每次都重复一次.不是很大,但需要考虑. (5认同)
  • @kap 我的团队对未使用的 lambda 变量的约定已变为`__ -&gt; true`(两个下划线),这是一个有效的 Java 标识符。您可以教您的 IDE 接受某些名称。 (4认同)
  • @GarretWilson当然,命名事情很好.出于类似的原因,我们将`Integer :: sum`替换为`(a,b) - > a + b`. (2认同)
  • @StuartMarks:"......我们决定不再在Java SE的未来版本中添加." 根据`Function.identity()`作为`t - > t`,似乎很奇怪`t - > true`是如此糟糕.我理解"我们厌倦了添加东西"的情绪,但不要把一致性和完整性抛到脑后.我不希望Java成为任意进出的大杂烩.令我担心的是,Java 8中遗漏了很多东西,因为"我们不想再添加",例如`Optional`是`Serializable`或`CharStream`.只是对我遇到的事情的一些思考和反馈. (2认同)
  • @GarretWilson如果我给人的印象是"我们厌倦了添加东西",那就错了.在我们考虑添加的功能接口上有一整套潜在的方法.在团队讨论中有一个刻意的判断呼吁,添加它们并没有产生足够的好处来证明这项工作的合理性.对于像CharStream这样的东西,这种权衡更加清晰; 几乎重复的代码的数量将大大超过它(和其他原始流)的使用量. (2认同)

小智 6

没有番石榴

Boolean.TRUE::booleanValue
Run Code Online (Sandbox Code Playgroud)

  • 但这不是一个“谓词”,因为它不需要参数。 (15认同)
  • 您的方法引用可分配给Supplier &lt;Boolean&gt;,但不能分配给Predicate &lt;T&gt; (10认同)
  • 人们:**请停止投票!**这个答案是**明显不正确**。你**不能**写`Predicate&lt;Whatever&gt; p = Boolean.TRUE::booleanValue`,因为`booleanValue()`不接受任何参数。您只能将其用作“Supplier&lt;Boolean&gt;”(如丹尼尔所说),这不能回答问题(并且可能很少有用)。 (6认同)
  • 那很有意思。我不确定它是否能完全体现出请求的精神,但它可以为您带来创造力! (3认同)
  • 它不是一个谓词,它是一个方法引用,但它的优点是简洁且不强制提及未使用的参数。+1 顺便说一句,由于它避免使用具有严重模块化问题的 Guava,因此值得我点赞 ;) (2认同)

kri*_*arp 5

如果您正在 Spring 框架中寻找此内容:

org.springframework.data.util.Predicates支持这一点。

Predicates.isTrue(),Predicates.isFalse()