java 通过谓词使用java流过滤器时记录过滤器的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43555977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:31:55  来源:igfitidea点击:

Logging the result of filter while using java streams filter by predicate

javaloggingfilterjava-8java-stream

提问by rcipher222

The scenario is there are different types of filters I have created which filters the list of some objects based on the property of the object.

场景是我创建了不同类型的过滤器,它们根据对象的属性过滤一些对象的列表。

So for that I have created an AbstractObjectFilter class which inherited by every filter.
AbstractObjectFilter.java

为此,我创建了一个由每个过滤器继承的 AbstractObjectFilter 类。
抽象对象过滤器.java

public abstract class AbstractEventFilter
{
    protected abstract Predicate<IEvent> isEligible();

    public List<IEvent> getFilteredEvents(final List<IEvent> events)
    {
        return events.stream().filter(isEligible()).collect(Collectors.toList());
    }
}

So now every filter extends this class and overrides the isEligible() and in that function it returns the predicate based on its properties.

所以现在每个过滤器都扩展了这个类并覆盖了 isEligible() 并且在该函数中它返回基于其属性的谓词。

For eg:- MinNumOfPrizesFilter.java

例如:- MinNumOfPrizesFilter.java

public class MinimumNumOfPrizesFilter extends AbstractEventFilter
{
    private int minimumNumOfPrizes;

    public MinimumNumOfPrizesFilter(@NonNull int minimumNumOfPrizes)
    {
        this.minimumNumOfPrizes = minimumNumOfPrizes;
    }

    @Override
    protected Predicate<IEvent> isEligible()
    {
        return event -> event.getPrizeCount() >= minimumNumOfPrizes;
    }
}

Similarly there are many other filters I have created. There is one applyFilter function which iterate over the list of filter objects and keep applying filter by call getFilteredEvents function.

同样,我还创建了许多其他过滤器。有一个 applyFilter 函数,它遍历过滤器对象列表,并通过调用 getFilteredEvents 函数继续应用过滤器。

Now how can i log the fate of each event For example - "x1 event was filtered by MinNumOfPrizesFilter filter. x1's prize count - 10 , required min prize count - 20"

现在我如何记录每个事件的命运 例如 - “x1 事件被 MinNumOfPrizesFilter 过滤器过滤。x1 的奖品数量 - 10,所需的最小奖品数量 - 20”

回答by Jean-Fran?ois Savard

You can simply add brackets to your lambda expression and add the logging statement right before the validation :

您可以简单地在 lambda 表达式中添加括号并在验证之前添加日志语句:

return event -> {
    // LOG.info(event.getName() + " was filtered...") or whatever you use for logging.
    return event.getPrizeCount() >= minimumNumOfPrizes;
}

Note that there exists a peekoperation which is meant to be used mostly for logging on java streams :

请注意,存在一个peek主要用于登录 java 流的操作:

events.stream()
      .peek(event -> System.out.println("Filtering event" + event.getName()))
      .filter(isEligible())
      .collect(Collectors.toList());

but that is not helping here, as you need to log in AbstractEventFilterimplementations.

但这在这里没有帮助,因为您需要登录AbstractEventFilter实现。

回答by P.J.Meisch

perhaps not the prettiest solution, but it works and you only change your abstract base class:

也许不是最漂亮的解决方案,但它有效,您只需更改抽象基类:

abstract class AbstractEventFilter {

    private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
    private final String filterName = getClass().getSimpleName();

    protected abstract Predicate<IEvent> isEligible();

    private Predicate<IEvent> internalIsEligible() {
        return iEvent -> {
            boolean res = isEligible().test(iEvent);
            if (!res) {
                logger.info("event " + iEvent.toString() + " filtered by " + filterName);
            }
            return res;
        };
    }

    public List<IEvent> getFilteredEvents(final List<IEvent> events) {
        return events.stream().filter(internalIsEligible()).collect(Collectors.toList());
    }
}

you keep your derived classes implementing isELigible()as before, only in your getFilteredEventsmethod, you call the internalIsEligibablemethod instead.

你保持你的派生类isELigible()像以前一样实现,只有在你的getFilteredEvents方法中,你才调用该internalIsEligibable方法。