Java 8 - 更新同一流代码中的两个属性

Java 8 - Update two properties in same Stream code

我想知道是否有一种方法可以在 Stream lambda 代码中更新两次对象,我需要更新 class 的两个属性,我需要更新valuerecordsCount 属性

对象:

public class HistoricDataModelParsed {

private Date   startDate;
private Date   endDate;
private Double value;
private int    recordsCount;

}

我试过这样做:

val existingRecord = response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(null);


response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(existingRecord)
     .setValue(valueAdded)
     .setRecordsCount(amount);

但我得到了这个错误:“无法在原始类型 void 上调用 setRecordsCount(int)

所以我最后做了两次流来更新我需要的两个字段中的每一个

response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(existingRecord)
     .setValue(valueAdded);
                
 response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(existingRecord)
     .setRecordsCount(amount);      

有没有一种方法可以实现我所需要的而无需流式传输两次列表?

对象的状态不应在流中更改。它可能导致不一致的结果。但是您可以创建对象的新实例并通过构造函数传递新值。下面简单记录一下方法。记录基本上是不可变的 classes,没有 setter。吸气剂是变量的名称。 class 也适用于此示例。

record Temp(int getA, int getB) {
    @Override
    public String toString() {
        return "[" + getA + ", " + getB  +"]";
    }
}

一些数据

    List<Temp> list = List.of(new Temp(10, 20), new Temp(50, 200),
        new Temp(100, 200));

以及转型。具有新值的 Temp 的新实例与旧实例一起创建,以完全填充构造函数。否则,将传递现有对象。

List<Temp> result = list.stream().map(
        t -> t.getA() == 50 ? new Temp(2000, t.getB()) : t)
        .toList();

System.out.println(result);

版画

[[10, 20], [2000, 200], [100, 200]]

要回答 void 错误,你得到它是因为流期望值在流中继续,所以如果一个方法是无效的,它不会 returning 任何东西所以你会有到return吧。这是一个例子:

stream.map(t->{voidReturnMethod(t); return t;}).toList();

return 确保管道继续。

只需存储 orElse 的结果,然后在其上调用您的方法。

HistoricDataModelParsed record = 
    response.stream()
        .filter(dateTime -> fromDate.equals(dateTime.getStartDate()))
        .findAny()
        .orElse(existingRecord);

record.setValue(valueAdded)
record.setRecordsCount(amount);

setValue的return类型是void不是HistoricDataModelParsed。所以你不能调用 HistoricDataModelParsed class.

中的方法 setRecordsCount

您可以在 HistoricDataModelParsed 中添加一个方法,该方法接受 valuerecordsCount 的两个参数:

public void setValueAndCount(Double value, int count) {
    this.value = value;
    this.recordsCount = count;
}

然后在orElse之后调用这个方法:

response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(existingRecord)
     .setValueAndCount(valueAdded, amount);