2

I'm wondering if there is a way I can update two times an object in a Stream lambda code, I need to update two properties of a class, I need to update the value and the recordsCount properties

Object:

public class HistoricDataModelParsed {

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

}

I tried doing something like this:

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);

But I got this error: "Cannot invoke setRecordsCount(int) on the primitive type void"

So I ended up doing the stream two times to update each of the two fields I needed

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);      

Is there a way I can achieve what I need without the need to stream two times the list?

5
  • You shouldn't use Date. Commented Jul 30, 2021 at 22:13
  • What exactly is existingRecord? Commented Jul 31, 2021 at 10:13
  • @MCEmperor can you elaborate why? Commented Aug 2, 2021 at 21:35
  • @MohamedAneesA updated the question to add what is that variable Commented Aug 2, 2021 at 21:37
  • 1
    @xThunder Of course. Here is something. Furthermore, the new API (in the java.time package) is more complete, as it also models concepts not available in the old API, like periods and durations. Commented Aug 2, 2021 at 22:02

3 Answers 3

2

The return type of setValue is void and not HistoricDataModelParsed. So you cannot invoke the method setRecordsCount which is in HistoricDataModelParsed class.

You could have added a method in HistoricDataModelParsed which takes two parameters for value and recordsCount:

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

Then call this method after orElse:

response.stream()
     .filter(dateTime ->fromDate.equals(dateTime.getStartDate()))
     .findAny()
     .orElse(existingRecord)
     .setValueAndCount(valueAdded, amount);
Sign up to request clarification or add additional context in comments.

Comments

2

The state of an object should not change within a stream. It can lead to inconsistent results. But you can create new instances of the objects and pass new values via the constructor. Here is a simple record that demonstrates the method. Records are basically immutable classes that have no setters. The getters are the names of the variables. A class would also work in this example.

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

Some data

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

And the transformation. A new instance of Temp with new values is created along with the old ones to completely populate the constructor. Otherwise, the existing object is passed along.

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

System.out.println(result);

Prints

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

To answer the void error you got it's because a stream expects values to continue thru out the stream so if a method is void, it isn't returning anything so you would have to return it. Here is an example:

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

The return ensures the pipeline continues.

Comments

2

Simply store the result of orElse and then call your methods on it.

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.