在Java8中使用Predicate <T>实现过滤器

Tho*_*unk 2 java java-8

为了掌握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);
    }
}    
Run Code Online (Sandbox Code Playgroud)

所以我能够插入列表并检索列表.

我的下一步是实现一个通用的过滤方法:

public List<?> find(Class c, Predicate<?> predicate){
    List<?> result= repo.get(c);
    return (result==null)?new ArrayList<>():(List<?>)result.stream().filter(predicate);
}
Run Code Online (Sandbox Code Playgroud)

结果

java: incompatible types: java.util.function.Predicate<capture#1 of ?> cannot be converted to java.util.function.Predicate<? super capture#2 of ?>
Run Code Online (Sandbox Code Playgroud)

如何实现通用的查找方法?

我不得不承认,我不确定,设计与

Map<Class, List<?>> repo =new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

是个不错的选择.也许有更好的解决方案.

Roh*_*ain 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());
}
Run Code Online (Sandbox Code Playgroud)