具有以下阶级的:

public class TimeInterval {
    private ZonedDateTime time;
    private Double value1;
    private Double value2;
}

其中TimeInterval.time是一天中的时间间隔,我想要做的是按天分组并聚合值. 棘手的部分是,我想根据特定条件应用两种不同类型的聚合.

例如:

2018-01-01T00:00, 1.0, 2.0
2018-01-01T08:00, null, null
2018-01-01T16:00, 5.0, 6.0
2018-01-02T00:00, 1.0, 2.0
2018-01-02T08:00, 3.0, 4.0
2018-01-02T16:00, 5.0, 6.0
2018-01-03T00:00, null, null
2018-01-03T08:00, null, null
2018-01-03T16:00, null, null

应汇总为:

2018-01-01, 32.0 - nulls are replaced with 0.0 in this case
2018-01-02, 44.0 - all values valid
2018-01-03, null - all intervals with null values, final value is null

聚合函数是value1 * value2,但要点是,如果只有部分间隔是空值(上例中的2018-01-01),但如果所有的间隔都是空值,我希望当天的最终值为空值(上例中的2018-01-03),则希望将空值替换为0.0.

如何使用Java Streams实现这一点?

推荐答案

您可以使用

Map<LocalDate, Double> map = list.stream()
    .collect(groupingBy(ti -> ti.time.toLocalDate(),
        collectingAndThen(
            filtering(ti -> ti.value1 != null,
                mapping(ti -> ti.value1 * ti.value2, reducing(Double::sum))),
        o -> o.orElse(null))
    ));

通常,您会使用toMap收集器进行这样的缩减,但toMap不允许函数返回null.此外,将数字表达式和null混合在一起的条件表达式很难理解,很容易导致异常.

因此,此解决方案首先筛选null个值,使用reducing收集器生成一个Optional,当所有值都为null时,该值将为空,因此我们可以在最后一步使用orElse(null)将所需的null结果替换为空可选项.

Demo on onecompiler.com

Java相关问答推荐

Spring bootstrap @ Asmat注释与@ Routed

长音符

在现有Json文件中添加新记录

Java 8 RDX-如何设置单个选项卡标题文本的 colored颜色

Java Stream,需要更新列表对象列表

在for—each循环中的AnimationTimer中的if语句'

无法在org. openjfx:javafx—fxml:21的下列变体之间进行 Select

滚动视图&不能在alert 对话框中工作(&Q;&Q;)

在运行MVN测试时,为什么构建失败,并显示了java.lang.ClassNotFoundException:java.net.http.HttpResponse?

蒙蒂霍尔比赛结果不正确

Helidon 4和Http API

如何让JVM在SIGSEGV崩溃后快速退出?

使用正则表达式从字符串中提取多个值

使用Jackson库反序列化json

Oj算法 MatrixR032从字符串、归一化和余弦相似度计算创建

带有可选部分的Java DateTimeForMatter

使用for循环时出现堆栈溢出错误,但如果使用if块执行相同的操作,则不会产生错误

Java List有一个在一个位置添加多个元素的方法,但我找不到一个在一个位置删除多个元素的方法

java.lang.NoSuchMethodError:';org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream$Builder org.apache.poi-poi-ooxml-5.2.4

如何使JOOQ渐变脚本不重新创建表未更改的类?