流组传入排序事件

问题描述 投票:0回答:2

我有一系列事件,每个事件包含时间戳、设备、序列号和测量值。

class Event {
    private String device;
    private String description;
    private String serialnumber;
    private Measurement measurement;
}

class Measurement {
    private LocalDateTime timestamp;
    private int value;
}

我有一个这些事件流,我想将它们聚合成一个更简单的结构,删除序列号,然后按设备对它们进行分组,然后按时间戳和值对测量结果进行排序。

{device: "device_1", description: "first device", serialnumber: "1", measurement: { timestamp: 2022-04-23T18:20:22Z, value: 180}}
{device: "device_2", description: "second device", serialnumber: "2", measurement: { timestamp: 2022-04-23T18:20:28Z, value: 120}}
{device: "device_2", description: "second device", serialnumber: "2", measurement: { timestamp: 2022-04-23T18:20:20Z, value: 160}}
{device: "device_1", description: "first device", serialnumber: "1", measurement: { timestamp: 2022-04-23T18:20:22Z, value: 170}}
[
    {
        device: "device_1",
        description: "first device",
        measurements: [
            { timestamp: 2022-04-23T18:20:22Z, value: 170},
            { timestamp: 2022-04-23T18:20:22Z, value: 180}
        ]
    },
    {
        device: "device_2",
        description: "second device",
        measurements: [
            { timestamp: 2022-04-23T18:20:20Z, value: 160},
            { timestamp: 2022-04-23T18:20:28Z, value: 120}
        ]
    }
]

我成功地通过创建一个“构建器”类来获得所需的格式,您可以在其中插入事件,然后以正确的格式/顺序处理这些事件并添加到数据成员中。 但是,我认为最好以某种方式即时实现这一目标,而无需另一个额外的类,而是使用

groupingBy
toMap
(以及其他?)流方法。

java events java-stream
2个回答
2
投票

您可以按

Event
device
对象进行分组,然后将
Measurement
收集到
TreeSet
中,并按
timestamp
value
对它们进行排序。

Map<String, TreeSet<Measurement>> map = dataSource.stream()
    .collect(Collectors.groupingBy(
                    Event::getDevice,
                    Collectors.mapping(Event::getMeasurement,
                            Collectors.toCollection(TreeSet::new)
                    )
            )
    );

在这种情况下,您需要在

Comparable
类上实现
Measurement
接口并提供
compareTo
的定义,或者使用所需的排序逻辑将
Comparator
传递给
TreeSet
。在这两种情况下,请记住提供正确的定义,以便“与 equals 一致”。根据Comparable
界面:

强烈建议(尽管不是要求)自然排序与 equals 保持一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然顺序与 equals 不一致的元素(或键)一起使用时表现“奇怪”。特别是,这样的排序集(或排序映射)违反了集合(或映射)的一般契约,该契约是根据 equals 方法定义的。

@Data @AllArgsConstructor class Event { private String device; private String description; private String serialnumber; private Measurement measurement; } @Data @AllArgsConstructor class Measurement implements Comparable<Measurement> { private LocalDateTime timestamp; private int value; //Redefinition of Measurement's natural ordering by its timestamp and value @Override public int compareTo(Measurement m) { Comparator<Measurement> cmp = Comparator.comparing(Measurement::getTimestamp) .thenComparing(Measurement::getValue); return cmp.compare(this, m); } }
这是 
OneCompiler

的演示


2
投票
Map<String, List<Measurement>>

获得

groupingBy
Map<String, List<Measurement>> result = 
        events.stream()
                .collect(Collectors.groupingBy(Event::getDevice,
                         Collectors.mapping(Event::getMeasurement, Collectors.toList())));

	
© www.soinside.com 2019 - 2024. All rights reserved.