项目中创建形如以下的类:
@Data
public class A{
private Long id;
private List<B> b;
@Data
public static class B{
private String id;
private String name;
}
然后项目中对此类型的集合进行数据筛选,当然,普通循环遍历很容易实现,但是用lambda更加简洁。
使用lambda后,报出了如下错误:
Error:(310, 21) java: 对于collect(java.util.stream.Collector<java.lang.Object,capture#1, 共 ?,java.util.List<java.lang.Object>>), 找不到合适的方法
方法 java.util.stream.Stream.<R>collect(java.util.function.Supplier<R>,java.util.function.BiConsumer<R,? super capture#2, 共 ? extends XXXX.A.B>,java.util.function.BiConsumer<R,R>)不适用
(无法推断类型变量 R
(实际参数列表和形式参数列表长度不同))
方法 java.util.stream.Stream.<R,A>collect(java.util.stream.Collector<? super capture#2, 共 ? extends XXXX.A.B,A,R>)不适用
(无法推断类型变量 R,A,capture#3, 共 ?,T
(参数不匹配; java.util.stream.Collector<capture#2, 共 ? extends com.arvato.minipro.bean.dto.crm.response.CrmOrder.CrmOrderInfo,capture#4, 共 ?,java.util.List<capture#2, 共 ? extends XXXX.A.B>>无法转换为java.util.stream.Collector<? super capture#2, 共 ? extends XXXX.A.B,capture#4, 共 ?,java.util.List<capture#2, 共 ? extends XXXX.A.B>>))
发现问题在于在代码中使用了通配符?以及泛型,编译器直接懵逼,不知道要塞哪种类型到集合中返回,因此,只需要显式指定一下集合类型就可以了。
Supplier<List<A.B>> supplier = () -> new ArrayList<>();
List<? extends A.B> orderList = pageResult.getData()
.stream()
.filter(o1-> o1.getNo() != null && o1.getNo().contains(o.getCode()))
.filter(o1 -> Double.parseDouble(o1.getPrice()) > 0)
.collect(Collectors.toCollection(supplier));
主要就是把Collectors.toList改为了Collectors.toCollection(supplier),supplier已经在上边进行了声明并指定了参数类型。
查看Supplier源码:
/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
根据注释可以很容易知道这个类就是指定具体的返回的具体类型的,如果遇到上述情况,可通过此方法解决。