流组传入排序事件
Stream group incoming sort events
我有一系列事件,每个事件都包含时间戳、设备、序列号和测量值。
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}
]
}
]
我已经通过创建一个“生成器”class 成功地获得了所需的格式,您可以在其中插入事件,然后将这些事件处理并添加到正确的 format/order 中的数据成员中。
但是,我认为如果不使用其他额外的 class,而是使用 groupingBy
和 toMap
(以及其他?)流方法,以某种方式即时实现这一点会更好。
您可以使用 groupingBy
获得 Map<String, List<Measurement>>
如果这是您要找的:
Map<String, List<Measurement>> result =
events.stream()
.collect(Collectors.groupingBy(Event::getDevice,
Collectors.mapping(Event::getMeasurement, Collectors.toList())));
我想出了这个解决方案,假设每个设备不能有多个具有相同时间戳和值的测量。
我知道这可能是一个限制,但由于我看不到任何对收集器收集的子集进行排序的方法,我决定使用 TreeSet 来存储分组的测量值,以便它们将根据按照他们的自然顺序。
class Event {
private String device;
private String description;
private String serialnumber;
private Measurement measurement;
public Event(String device, String description, String serialnumber, Measurement measurement) {
this.device = device;
this.description = description;
this.serialnumber = serialnumber;
this.measurement = measurement;
}
//... getters and setters ...
}
class Measurement implements Comparable<Measurement> {
private LocalDateTime timestamp;
private int value;
public Measurement(LocalDateTime timestamp, int value) {
this.timestamp = timestamp;
this.value = value;
}
//... getters and setters ...
//Redefinition of the natural ordering by timestamp and value
@Override
public int compareTo(Measurement m) {
Comparator<Measurement> cmp = Comparator.comparing(Measurement::getTimestamp).thenComparing(Measurement::getValue);
return cmp.compare(this, m);
}
public String toString(){
return String.format("%s - %d", timestamp, value);
}
}
public class Test {
public static void main(String[] args) {
List<Event> dataSource = new ArrayList<>(List.of(
new Event("device_1", "first device", "1", new Measurement(LocalDateTime.parse("2022-04-23T18:20:22"), 180)),
new Event("device_2", "second device", "2", new Measurement(LocalDateTime.parse("2022-04-23T18:20:28"), 120)),
new Event("device_2", "second device", "2", new Measurement(LocalDateTime.parse("2022-04-23T18:20:20"), 160)),
new Event("device_1", "first device", "1", new Measurement(LocalDateTime.parse("2022-04-23T18:20:22"), 170))));
Map<String, TreeSet<Measurement>> map = dataSource.stream()
.collect(Collectors.groupingBy(Event::getDevice, Collectors.mapping(Event::getMeasurement, Collectors.toCollection(TreeSet::new))));
for (String key: map.keySet()){
System.out.printf("%s => %s%n", key, map.get(key));
}
}
}
我有一系列事件,每个事件都包含时间戳、设备、序列号和测量值。
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}
]
}
]
我已经通过创建一个“生成器”class 成功地获得了所需的格式,您可以在其中插入事件,然后将这些事件处理并添加到正确的 format/order 中的数据成员中。
但是,我认为如果不使用其他额外的 class,而是使用 groupingBy
和 toMap
(以及其他?)流方法,以某种方式即时实现这一点会更好。
您可以使用 groupingBy
获得 Map<String, List<Measurement>>
如果这是您要找的:
Map<String, List<Measurement>> result =
events.stream()
.collect(Collectors.groupingBy(Event::getDevice,
Collectors.mapping(Event::getMeasurement, Collectors.toList())));
我想出了这个解决方案,假设每个设备不能有多个具有相同时间戳和值的测量。
我知道这可能是一个限制,但由于我看不到任何对收集器收集的子集进行排序的方法,我决定使用 TreeSet 来存储分组的测量值,以便它们将根据按照他们的自然顺序。
class Event {
private String device;
private String description;
private String serialnumber;
private Measurement measurement;
public Event(String device, String description, String serialnumber, Measurement measurement) {
this.device = device;
this.description = description;
this.serialnumber = serialnumber;
this.measurement = measurement;
}
//... getters and setters ...
}
class Measurement implements Comparable<Measurement> {
private LocalDateTime timestamp;
private int value;
public Measurement(LocalDateTime timestamp, int value) {
this.timestamp = timestamp;
this.value = value;
}
//... getters and setters ...
//Redefinition of the natural ordering by timestamp and value
@Override
public int compareTo(Measurement m) {
Comparator<Measurement> cmp = Comparator.comparing(Measurement::getTimestamp).thenComparing(Measurement::getValue);
return cmp.compare(this, m);
}
public String toString(){
return String.format("%s - %d", timestamp, value);
}
}
public class Test {
public static void main(String[] args) {
List<Event> dataSource = new ArrayList<>(List.of(
new Event("device_1", "first device", "1", new Measurement(LocalDateTime.parse("2022-04-23T18:20:22"), 180)),
new Event("device_2", "second device", "2", new Measurement(LocalDateTime.parse("2022-04-23T18:20:28"), 120)),
new Event("device_2", "second device", "2", new Measurement(LocalDateTime.parse("2022-04-23T18:20:20"), 160)),
new Event("device_1", "first device", "1", new Measurement(LocalDateTime.parse("2022-04-23T18:20:22"), 170))));
Map<String, TreeSet<Measurement>> map = dataSource.stream()
.collect(Collectors.groupingBy(Event::getDevice, Collectors.mapping(Event::getMeasurement, Collectors.toCollection(TreeSet::new))));
for (String key: map.keySet()){
System.out.printf("%s => %s%n", key, map.get(key));
}
}
}