为了掌握Java8,我试图实现一个简单的Repo来存储不同对象的列表。
我的出发点是:
public class MyRepo {
Map<Class, List<?>> repo =new HashMap<>();
public List<?> get(Class c){
List<?> result= repo.get(c);
return (result==null)?new ArrayList<>():(List<?>) result;
}
public void put(Class c,List<?> l){
repo.put(c, l);
}
}
所以我可以插入列表并检索列表。
我的下一步是实现一般的过滤方法:
public List<?> find(Class c, Predicate<?> predicate){
List<?> result= repo.get(c);
return (result==null)?new ArrayList<>():(List<?>)result.stream().filter(predicate);
}
导致
java: incompatible types: java.util.function.Predicate<capture#1 of ?> cannot be converted to java.util.function.Predicate<? super capture#2 of ?>
如何实现通用的查找方法?
我不得不承认,我不确定,设计是否
Map<Class, List<?>> repo =new HashMap<>();
是个不错的选择。也许有更好的解决方案。
答案 0 :(得分:6)
首先,您应该使您的方法通用,这将让编译器决定您传递的Predicate
,并相应地推断出特定类型。此外,result.stream().filter(predicate)
会为您提供Stream
而不是List
。您需要在List
。
此外,由于您已经拥有get(Class<T>)
方法,因此您可以使用该方法,而不是在repo.get(c)
方法中执行find()
方法。你也可以在这里使用java.util.Optional
课程:
Map<Class, List<?>> repo =new HashMap<>();
public <T> List<T> get(Class<T> c){
return Optional.ofNullable((List<T>)repo.get(c)).orElse(new ArrayList<>());
}
public <T> void put(Class<T> c,List<T> l){
repo.put(c, l);
}
public <T> List<T> find(Class<T> c, Predicate<T> predicate){
return get(c).stream().filter(predicate).collect(Collectors.toList());
}
答案 1 :(得分:3)
您需要修复方法签名。通用通配符类型本质上是独立的 - Java编译器没有理由相信一个?
类型与另一个?
类型有任何关联。
尝试:
public <T> List<T> get(Class<T> c)
public <T> void put(Class<T> c, List<T> list)
public <T> List<T> find(Class<T> c, Predicate<T> predicate)
这个可配置的<T>
参数允许调用者指定他们希望的任何类型,但也让编译器知道&#34;嘿,这个List<T>
和Predicate<T>
?那个T
是相同的,所以你可以完全过滤&#34;