Logging the result of filter while using java stre

2019-05-06 20:06发布

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

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.

For eg:- 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.

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"

2条回答
相关推荐>>
2楼-- · 2019-05-06 20:15

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

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

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

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 AbstractEventFilter implementations.

查看更多
欢心
3楼-- · 2019-05-06 20:24

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 getFilteredEvents method, you call the internalIsEligibable method instead.

查看更多
登录 后发表回答