简体   繁体   English

Java 8 个流 - 在 Collectors.groupingBy 中处理空值

[英]Java 8 Streams - Handle Nulls inside Collectors.groupingBy

I have a list of objects in variable "data".我有一个变量“数据”中的对象列表。 I want to filter them (on ActivityType='Deal_Lost') and then group them using one of the field (DealLostReason) and store in a map with DealLostReason and respective count.我想过滤它们(在 ActivityType='Deal_Lost' 上),然后使用其中一个字段(DealLostReason)对它们进行分组,并使用 DealLostReason 和相应的计数存储在 map 中。

Below method works perfectly fine when there are no NULL values returned by c.getDealLostReason().当 c.getDealLostReason() 返回没有 NULL 值时,以下方法工作得很好。 However, if there is a null value in any of the record, it just returns null instead of grouped values.但是,如果任何记录中有 null 值,它只会返回 null 而不是分组值。

Map<Object, Long> collect = data.stream().
    filter(c -> c.getActivityType().equals(ActivityTypeEnum.Deal_Lost))
    .collect(Collectors.groupingBy(c -> { 
        return c.getDealLostReason(); }, Collectors.counting()))));

Can anyone help me on how to handle null values inside lambda expression.任何人都可以帮助我如何处理 lambda 表达式中的 null 值。 I want the null values to be calculated as "Other".我希望将 null 值计算为“其他”。 ie if any record has null, it should be calculated as "OTHER".即如果任何记录有null,则应计算为“OTHER”。 Below is the SQL query I am trying to achieve.下面是我试图实现的 SQL 查询。

USE egcity;
SELECT 
    CASE WHEN dealLostReason IS NULL THEN 'Other' ELSE dealLostReason END,
    COUNT(*) from LeadActivity
WHERE 
        activity_date_time>='2021-04-01' AND activity_date_time<='2021-05-01'
AND activityType = 'Deal_Lost'
GROUP BY dealLostReason;

在此处输入图像描述

You can use ternary operator to map null having objects counts to OTHER您可以将三元运算符用于 map null对象计数为OTHER

Map<Object, Long> collect = data.stream()
           .filter(c->c.getActivityType().equals(ActivityTypeEnum.Deal_Lost))
           .collect(Collectors.groupingBy(c -> c.getDealLostReason() == null ? "OTHER" : c.getDealLostReason(),Collectors.counting())));
                                      

null s should be avoided at the source. null应该从源头上避免。 That said, handling null s mid-stream can be done using Optional s.也就是说,可以使用Optional来处理null的中流。 Here's a dirty little gist to get you started.这是一个肮脏的小要点,可以帮助您入门。

    Map<Object, Long> collect = data.stream()
            .map( x -> Optional.of( x ).orElseGet( () -> Something.defaultSomething() ) )
            .filter( c -> c.getActivityType().equals(ActivityTypeEnum.Deal_Lost))
            .collect( Collectors.groupingBy( c ->
            {
                return c.getDealLostReason();
            }, Collectors.counting()));

with the defaultSomething some implementation of the type representing the absent value.使用defaultSomething表示缺少值的类型的一些实现。

Even better would be to postpone the optional-unwrapping to the very last moment;更好的办法是将可选展开推迟到最后一刻; in this case the query construction: ie Don't need to know, don't wanna know .在这种情况下查询构造:即不需要知道,不想知道

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

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