谓词中的运算符作为 lambda 表达式中的参数
operators in predicate as argument in lambda expression
我需要在 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 有什么问题?如果您在
中找到答案,请为规格页面提供任何 link
发生的事情是您正在使用 raw java.util.function.Predicate
,test()
方法如下所示:
public void test(Object o) { ... }
这就是您得到编译时错误的原因:参数类型为 Object
并且数字运算符(<
、>
)不适用于类型 Object
。
但是,如果您使用类型参数为 Integer
的泛型 java.util.function.Predicate
,test()
方法将如下所示:
public void test(Integer i) { ... }
在这种情况下,数字运算符 (>
、<
) 对于提供的参数类型 (Integer
) 是有效的,不需要强制转换。
此外,我利用 Java8 中的 Stream API 来缩短您的方法实现:
public static int add(List<Integer> numList, Predicate<Integer> predicate) {
return numList.stream().filter(predicate).mapToInt(i -> i).sum();
}
有了这样的方法实现,现在所有这些陈述将完全有效:
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));
System.out.println("Add 4 Multiples: "+add(numList, n -> n % 4 == 0));
您忽略了 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 操作而不是方法中。
祝你好运!
我需要在 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 有什么问题?如果您在
中找到答案,请为规格页面提供任何 link发生的事情是您正在使用 raw java.util.function.Predicate
,test()
方法如下所示:
public void test(Object o) { ... }
这就是您得到编译时错误的原因:参数类型为 Object
并且数字运算符(<
、>
)不适用于类型 Object
。
但是,如果您使用类型参数为 Integer
的泛型 java.util.function.Predicate
,test()
方法将如下所示:
public void test(Integer i) { ... }
在这种情况下,数字运算符 (>
、<
) 对于提供的参数类型 (Integer
) 是有效的,不需要强制转换。
此外,我利用 Java8 中的 Stream API 来缩短您的方法实现:
public static int add(List<Integer> numList, Predicate<Integer> predicate) {
return numList.stream().filter(predicate).mapToInt(i -> i).sum();
}
有了这样的方法实现,现在所有这些陈述将完全有效:
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));
System.out.println("Add 4 Multiples: "+add(numList, n -> n % 4 == 0));
您忽略了 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 操作而不是方法中。
祝你好运!