【问题标题】:Logging the result of filter while using java streams filter by predicate通过谓词使用java流过滤器时记录过滤器的结果
【发布时间】:2017-09-19 05:44:51
【问题描述】:

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

为此,我创建了一个 AbstractObjectFilter 类,它被每个过滤器继承。
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());
    }
}

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

例如:- 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;
    }
}

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

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

【问题讨论】:

  • 这里的 lambda 表达式有什么意义?相比于传统的让AbstractEventFilter直接实现Predicate&lt;IEvent&gt;,子类只需要实现test方法的做法,不是简化。
  • 顺便说一句,用@NonNull 注释int 变量是没有意义的,因为int 的值永远不可能是null

标签: java logging filter java-8 java-stream


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 用这个你记录过滤和未过滤的值
  • @P.J.Meisch 我知道。 peek 操作不适合这里,只是在信息上添加了它,因为它对使用 java-streams 进行日志记录很有帮助。
  • 你需要在每个派生类中实现它
  • @P.J.Meisch 鉴于谓词在任何实现中都可能不同,并且 OP 想要打印这些信息(即 minimumNumOfPrizes),这是需要的。
【解决方案2】:

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

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());
    }
}

你让你的派生类像以前一样实现isELigible(),只是在你的getFilteredEvents方法中,你调用internalIsEligibable方法。

【讨论】:

  • 如何打印 minimumNumOfPrizes ?
  • 赞成只记录那些被过滤掉的。
猜你喜欢
  • 1970-01-01
  • 2020-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
相关资源
最近更新 更多