找不到适合 collect/reduce 的方法 - 无法使用 stream() 对整数列表求和
No suitable method found for collect/reduce - Can't sum a list of Integers with stream()
在输入中,我有一个整数和字符串列表。
第一个流工作正常,第二个流工作直到过滤器,我不知道为什么。我的代码:
import java.util.List;
import java.util.stream.*;
public class MixedSum {
public int sum(List<?> mixed) {
int m = mixed.stream().filter(x -> x instanceof String).map(x -> Integer.parseInt((String) x)).collect(Collectors.summingInt(Integer::intValue));
int n = mixed.stream().filter(x -> x instanceof Integer).collect(Collectors.summingInt(Integer::intValue));
return m + n;
}
}
我有这个错误:
error: no suitable method found for collect(Collector<Integer,CAP#1,Integer>)
int n = mixed.stream().filter(x -> x instanceof Integer).collect(Collectors.summingInt(Integer::intValue));
^
method Stream.<R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super CAP#2>,BiConsumer<R#1,R#1>) is not applicable
(cannot infer type-variable(s) R#1
(actual and formal argument lists differ in length))
method Stream.<R#2,A>collect(Collector<? super CAP#2,A,R#2>) is not applicable
(inferred type does not conform to upper bound(s)
inferred: CAP#2
upper bound(s): Integer,Object)
where R#1,T,R#2,A are type-variables:
R#1 extends Object declared in method <R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super T>,BiConsumer<R#1,R#1>)
T extends Object declared in interface Stream
R#2 extends Object declared in method <R#2,A>collect(Collector<? super T,A,R#2>)
A extends Object declared in method <R#2,A>collect(Collector<? super T,A,R#2>)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?
1 error
编译器无法推断类型。您需要像在第一步中那样进行投射:
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.map(x -> (int) x)
.collect(Collectors.summingInt(Integer::intValue));
或者如果你想使用方法参考
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.map(Integer.class::cast)
.collect(Collectors.summingInt(Integer::intValue));
在第二个流中应用方法引用 Integer::intValue
之前,您必须 cast 流的元素为 Integer
类型。
由于您只想获得整数基元的总和,因此无需求助于收集器的帮助,相反,您可以将对象流强制为 IntStream
并应用 sum()
方法。
int m = mixed.stream()
.filter(x -> x instanceof String)
.mapToInt(x -> Integer.parseInt((String) x))
.sum();
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.mapToInt(x -> (Integer) x)
.sum();
不需要重复两次,因为在源列表中你只能丢弃 Integer
和 String
类型的过滤器。所以你的方法最终归结为几行:
public int sum(List<?> mixed) {
return mixed.stream()
.mapToInt(x -> x instanceof Integer? (Integer) x : Integer.parseInt((String) x))
.sum();
}
注:
- 因为
Integer.parseInt()
可能会导致 NumberFormatException
如果转换失败,如果源列表至少包含一个 string,则流将不会产生值除了数字之外的其他符号。这就是所谓的 fail-fast 实现 如果您的意图不是 return 一个值以防无效数据而是 例外强调.
- 另一件值得指出的事情是,这段代码只有作为练习才有价值。在某些语言中,您可能会遇到联合类型 (
String | Number
) 和使用 instanceof
的运行时检查,但 Java 关心 type-safety 而在 real-life 场景中,您首先不应创建这样的混合集合。它可能是使用 row-type 集合或 Object
class 作为泛型类型完成的,以便 绕过编译器 。相反,像这样单独处理字符串值的来源会更干净、更少 error-prone:
strSource.stream().map(Integer::parseInt).collect(Collectors.toList());
因此 sum()
方法将免除多余的责任,并与以下合同签订合同:
list.stream().mapToInt(Integer::intValue).sum();
在输入中,我有一个整数和字符串列表。
第一个流工作正常,第二个流工作直到过滤器,我不知道为什么。我的代码:
import java.util.List;
import java.util.stream.*;
public class MixedSum {
public int sum(List<?> mixed) {
int m = mixed.stream().filter(x -> x instanceof String).map(x -> Integer.parseInt((String) x)).collect(Collectors.summingInt(Integer::intValue));
int n = mixed.stream().filter(x -> x instanceof Integer).collect(Collectors.summingInt(Integer::intValue));
return m + n;
}
}
我有这个错误:
error: no suitable method found for collect(Collector<Integer,CAP#1,Integer>) int n = mixed.stream().filter(x -> x instanceof Integer).collect(Collectors.summingInt(Integer::intValue)); ^ method Stream.<R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super CAP#2>,BiConsumer<R#1,R#1>) is not applicable (cannot infer type-variable(s) R#1 (actual and formal argument lists differ in length)) method Stream.<R#2,A>collect(Collector<? super CAP#2,A,R#2>) is not applicable (inferred type does not conform to upper bound(s) inferred: CAP#2 upper bound(s): Integer,Object) where R#1,T,R#2,A are type-variables: R#1 extends Object declared in method <R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super T>,BiConsumer<R#1,R#1>) T extends Object declared in interface Stream R#2 extends Object declared in method <R#2,A>collect(Collector<? super T,A,R#2>) A extends Object declared in method <R#2,A>collect(Collector<? super T,A,R#2>) where CAP#1,CAP#2 are fresh type-variables: CAP#1 extends Object from capture of ? CAP#2 extends Object from capture of ? 1 error
编译器无法推断类型。您需要像在第一步中那样进行投射:
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.map(x -> (int) x)
.collect(Collectors.summingInt(Integer::intValue));
或者如果你想使用方法参考
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.map(Integer.class::cast)
.collect(Collectors.summingInt(Integer::intValue));
在第二个流中应用方法引用 Integer::intValue
之前,您必须 cast 流的元素为 Integer
类型。
由于您只想获得整数基元的总和,因此无需求助于收集器的帮助,相反,您可以将对象流强制为 IntStream
并应用 sum()
方法。
int m = mixed.stream()
.filter(x -> x instanceof String)
.mapToInt(x -> Integer.parseInt((String) x))
.sum();
int n = mixed.stream()
.filter(x -> x instanceof Integer)
.mapToInt(x -> (Integer) x)
.sum();
不需要重复两次,因为在源列表中你只能丢弃 Integer
和 String
类型的过滤器。所以你的方法最终归结为几行:
public int sum(List<?> mixed) {
return mixed.stream()
.mapToInt(x -> x instanceof Integer? (Integer) x : Integer.parseInt((String) x))
.sum();
}
注:
- 因为
Integer.parseInt()
可能会导致NumberFormatException
如果转换失败,如果源列表至少包含一个 string,则流将不会产生值除了数字之外的其他符号。这就是所谓的 fail-fast 实现 如果您的意图不是 return 一个值以防无效数据而是 例外强调. - 另一件值得指出的事情是,这段代码只有作为练习才有价值。在某些语言中,您可能会遇到联合类型 (
String | Number
) 和使用instanceof
的运行时检查,但 Java 关心 type-safety 而在 real-life 场景中,您首先不应创建这样的混合集合。它可能是使用 row-type 集合或Object
class 作为泛型类型完成的,以便 绕过编译器 。相反,像这样单独处理字符串值的来源会更干净、更少 error-prone:
strSource.stream().map(Integer::parseInt).collect(Collectors.toList());
因此 sum()
方法将免除多余的责任,并与以下合同签订合同:
list.stream().mapToInt(Integer::intValue).sum();