在java.util.function.Predicate中执行IO操作

问题描述 投票:1回答:1

我有一个关于在java.util.function.Predicate中使用IO操作的问题。请考虑以下示例:

public class ClientGroupFilter implements Predicate<Client> {

    private GroupMapper mapper;
    private List<String> validGroupNames = new ArrayList<>(); 

    public ClientGroupFilter(GroupMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public boolean test(Client client) {
        // this is a database call
        Set<Integer> validsIds = mapper.getValidIdsForGroupNames(validGroupNames);    
        return client.getGroupIds().stream().anyMatch(validIds::contains);
    }

    public void permit(String name) {
        validGroupNames.add(name);
    }
}

如您所见,此过滤器接受任意数量的服务器组名称,这些名称在测试特定客户端时由映射器解析。如果客户端拥有其中一个有效的服务器组,则返回true。

现在,当然,如果将过滤器应用于多个客户端,这显然是非常低效的。所以,重构让我想到了这个:

public class ClientGroupFilter implements Predicate<Client> {

    private GroupMapper mapper;
    private List<String> validGroupNames = new ArrayList<>(); 
    private boolean updateRequired = true;
    private Set<Integer> validIds = new HashSet<>();

    public ClientGroupFilter(GroupMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public boolean test(Client client) {
        if(updateRequired) {
            // this is a database call
            validIds = mapper.getValidIdsForGroupNames(validGroupNames); 
            updateRequired = false;   
        }
        return client.getGroupIds().stream().anyMatch(validIds::contains);
    }

    public void permit(String name) {
        validGroupNames.add(name);
        updateRequired = true;
    }
}

当然,性能要好很多,但我仍然对解决方案不满意,因为我觉得java.util.function.Predicate不应该像这样使用。但是,我仍然希望能够提供快速解决方案来过滤客户端列表,而无需要求使用者将服务器组名称映射到其ID。

有没有人有更好的想法重构这个?

java
1个回答
0
投票

如果您的使用模式是多次调用permit,然后再使用Predicate<Client>而不再调用permit,则可以使用构建器将收集validGroupNames的代码与谓词的代码分开:

class ClientGroupFilterBuilder {
    private final GroupMapper mapper;
    private List<String> validGroupNames = new ArrayList<>(); 
    public ClientGroupFilter(GroupMapper mapper) {
        this.mapper = mapper;
    }
    public void permit(String name) {
        validGroupNames.add(name);
    }
    public Predicate<Client> build() {
        final Set<Integer> validIds = mapper.getValidIdsForGroupNames(validGroupNames);
        return new Predicate<Client>() {
            @Override
            public boolean test(Client client) {
                return client.getGroupIds().stream().anyMatch(validIds::contains);
            }
        }
    }
}

这限制了validIds的建设到我们构建Predicate<Client>的程度。一旦构造了谓词,就不需要进一步的输入。

© www.soinside.com 2019 - 2024. All rights reserved.