谓词中的运算符作为lambda表达式中的参数

时间:2015-06-14 15:51:11

标签: java lambda type-conversion java-8 predicate

我需要在lambda表达式中使用Predicate作为参数。我尝试了一个示例代码,但看到了编译错误。 我看到编译器对不同的参数采用不同的谓词。所以谓词参数n -> true and n -> false有效但n -> n%4 == 0无效。

编译错误是:

The operator % is undefined for the argument type(s) Object, int

我修好了(看下面的替换代码),但我问我是否应该修复它,为什么?我不确定我是否遗漏了一些基本的东西。

以下是完整的代码:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class PredicateAsArgumentInLambdaExpression {

        public static int add(List<Integer> numList, Predicate predicate) {
            int sum = 0;
            for (int number : numList) {
                if (predicate.test(number)) {
                    sum += number;
                }
            }
            return sum;
        }

        public static void main(String args[]){
            List<Integer> numList = new ArrayList<Integer>();
            numList.add(new Integer(10));
            numList.add(new Integer(20));
            numList.add(new Integer(30));       
            numList.add(new Integer(40));       
            numList.add(new Integer(50));

            System.out.println("Add Everything: "+add(numList, n -> true));
            System.out.println("Add Nothing: "+add(numList, n -> false));
//          System.out.println("Add Less Than 25: "+add(numList, n -> n < 25)); Compiler says: The operator < is undefined for the argument type(s) Object, int
            System.out.println("Add Less Than 25: "+add(numList, n -> Integer.valueOf((int)n) < Integer.valueOf("25")));
//          System.out.println("Add 4 Multiples: "+add(numList, n -> n % 4 == 0)); //Compiler says: The operator % is undefined for the argument type(s) Object, int
            System.out.println("Add 4 Multiples: "+add(numList, n -> Integer.valueOf((int)n) % Integer.valueOf("4")==0));
        }
}

注释掉的代码不起作用,紧接着下面的代码就是替换代码。代码按原样运行,但我希望注释掉的代码应该有效!对于java.util.function.Predicate中的Predicate来说,这是不是没有问题?如果您找到答案,请提供规格页面的任何链接。

2 个答案:

答案 0 :(得分:5)

正在发生的事情是您正在使用原始 java.util.function.Predicate<Directory /var/www/secundary.mysite.com/web> Options -Includes +ExecCGI AllowOverride All RewriteEngine On RewriteCond %{REQUEST_URI} !^/bundles(.*)$ [NC] RewriteRule ^.*$ - [F] </Directory> 方法看起来像这样:

test()

这就是您遇到编译时错误的原因:参数类型为public void test(Object o) { ... } ,数字运算符(Object<)不适用于{{1}类型}。

但是,如果您使用类型参数为>的通用java.util.function.PredicateObject方法将如下所示:

Integer

在这种情况下,数字运算符(test()public void test(Integer i) { ... } )对提供的参数类型(>)有效,并且不需要强制转换。

另外,我利用Java8中的Stream API缩短了方法实现:

<

实现这样的方法,现在所有这些语句都是完全有效的:

Integer

答案 1 :(得分:1)

您在add方法中忽略了通用参数。如果您从常规Predicate切换到Predicate<Integer>,则n会在操作前自动转换为Integer

简而言之,而不是:

public static int add(List<Integer> numList, Predicate predicate) {

你应该尝试:

public static int add(List<Integer> numList, Predicate<Integer> predicate) {

之后,您之前的代码:

n -> Integer.valueOf((int)n) < Integer.valueOf("25")
n -> Integer.valueOf((int)n) % Integer.valueOf("4")==0

可以简单地

n -> n < 25
n -> n % 4 == 0

另外效率更高。

这只是一个匹配方法期望与您提供的内容相关的问题。由于没有通用术语,Java希望Predicate默认接收类型Object,并且由于Integer扩展Object,因此它假定这是您传递的类型。有了它,它期望Integer,并且公开了与Integer相关的所有方法和运算符。

这是一个在调用方法之前发生的有点不可见的操作,这就是为什么你的警告是在lambda操作上而不是在方法中。

祝你好运!