简体   繁体   English

如果过滤值为 null,如何跳过 stream 过滤器?

[英]How to skip stream filter if filtered value is null?

I have a list of Java objects.我有一个 Java 对象的列表。 In database some of objects has got field nextSyncDate and some not.在数据库中,有些对象有字段nextSyncDate而有些则没有。 What I want to do is to put filter on java stream but only if this field exists and is for example greater than today date.我想要做的是在 java stream 上放置过滤器,但前提该字段存在并且例如大于今天的日期。 So simplify, I want to get objects which nextSyncDate is greater than today and objects which hasn't got this field (getting NullPointException after get() on this field).所以简化,我想获得nextSyncDate大于今天的对象和没有这个字段的对象(在这个字段上get()之后得到 NullPointException )。

I have tried something like this but it's not working like I want to..我已经尝试过这样的事情,但它并没有像我想要的那样工作..

List<MyObjects> objects;
objects.stream()
    .filter(obj -> Objects.nonNull(obj.getNextSyncDate()) && obj.getNextSyncDate().before(new Date()))

On the other hand, all objects has got field counter .另一方面,所有对象都有字段counter What I want to do additionally is to set nextSyncDate (for example for tomorrow) for every object which counter is greater than 15. I tried to .map() objects before .filter() but it's also not working.我还想做的是为每个counter大于 15 的 object 设置nextSyncDate (例如明天)。我尝试在.filter()之前设置.map()对象,但它也不起作用。

When creating a stream, you are not directly modifying its source.创建 stream 时,您不会直接修改其源代码。 You need to collect the data.您需要收集数据。 Your filter seems to work as intended.您的过滤器似乎按预期工作。 I would personally not recommend having a filtered stream with side effects (do your " counter > 15 then set nextSyncDate " logic somewhere else) but you could do it with another stream operation such as peek ( map is for transformation which isn't necessary in your case but could be used):我个人不建议使用带有副作用的过滤 stream (做你的“ counter > 15然后在其他地方设置nextSyncDate ”逻辑),但你可以用另一个 stream 操作来做到这一点,例如peekmap中的转换是不必要的你的情况,但可以使用):

List<MyObjects> objects = /* omitted */;
List<MyObjects> filteredObjects = objects.stream()
    .peek(MyObjects::setNextSycDateWithSomeLogic())
    .filter(obj -> Objects.nonNull(obj.getNextSyncDate()) && obj.getNextSyncDate().before(new Date()))
    .collect(Collectors.toList());

The filter can include the counter requirement as well:过滤器也可以包括counter要求:

    final Date TODAY = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
    final int COUNTER_THRESHOLD = 15;
    objects.stream()
            .filter(obj -> Objects.nonNull(obj.getNextSyncDate())
                    && obj.getNextSyncDate().before(TODAY)
                    && obj.getCounter() > COUNTER_THRESHOLD)

The intermediate stream provided by the filter has the objects which need to be updated, so a forEach can be applied:过滤器提供的中间 stream 有需要更新的对象,因此可以应用 forEach:

    final Date TODAY = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
    final Date TOMORROW = Date.from(LocalDate.now().plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
    final int COUNTER_THRESHOLD = 15;
    objects.stream()
            .filter(obj -> Objects.nonNull(obj.getNextSyncDate())
                    && obj.getNextSyncDate().before(TODAY)
                    && obj.getCounter() > COUNTER_THRESHOLD)
            .forEach(obj -> obj.setNextSyncDate(TOMORROW));

Also, consider using LocalDate instead of deprecated Date.此外,请考虑使用 LocalDate 而不是弃用的 Date。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM