Java 11 here. I have a 2 List<Fizzbuzz>
instances, latest
and current
. The "latest" list is the list of latest Fizzbuzzes, hot off the press. The "current" list is the list of Fizbuzzes that I have in my database. I am comparing these lists.
I need to compare these lists and create a 3rd list, additions
, which contains any Fizzbuzzes from the latest
list that are not found inside the current
list. Its a list of "new" Fizzbuzzes that the database does not have on record.
Furthermore, I need to set each addition's processedAt
field (Instant
) to the same current date/time. I'd like to try and accomplish this all inline using the Java Stream API. I can accomplish this the "old fashioned" way:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
List<Fizzbuzz> additions = new ArrayList<>();
Instant now = Instant.now();
for (Fizzbuzz latest : latestList) {
if (!currentList.contains(latest)) {
latest.setProcessedAt(now);
additions.add(latest);
}
}
My best attempt using the Java Stream API is:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
Instant now = Instant.now();
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.forEach(addition -> {
addition.setProcessedAt(now);
})
.collect(Collectors.toList());
This generates a compiler error because forEach
doesn't return anything. Can anyone spot where I'm going awry?
CodePudding user response:
You may use Stream.peek
, it allows to apply an operation on each element and doesn't keep the result (if there is any) and resume the stream
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.peek(addition -> addition.setProcessedAt(now))
.collect(Collectors.toList());
To a apply a modifying operation, that would transform the data into something else, you need Stream.map
CodePudding user response:
You need to create Instant as a final variable to use it in lamda expression
CodePudding user response:
A set operation and List.forEach()
Streams should not have side effects. Therefore you should not modify any stream element from within a stream operation. So I recommend that you don’t use streams at all for your two requirements.
List<Fizzbuzz> additions = new ArrayList<>(latestList);
additions.removeAll(currentList);
Instant now = Instant.now();
additions.forEach(addition -> addition.setProcessedAt(now));
The first two lines find the fizzbuzzes from latestList
that are not in currentList
. The removeAll
method is referred to as a set operation, not because it works on sets, but because it is used for finding the something like the set difference between two collections (in this case two lists). (Other set operations are addAll()
for a union and retainAll()
for an intersection.)
Then the last two lines set processedAt
as required.