Reputation: 4319
I am curious, if it is somehow possible, to not always go just straight within a stream. Imagine this sample code:
List<Employee> employees = [...];
employees.stream()
.map(Employee::getCity)
.map(City::getCountry)
.map(countryService::determineHazardLevel)
.filter(level -> level > 5) // integer
// this line not possible anymore as I drifted away from my employees ...
.forEach(employee -> employee.setPriority(HIGH))
I iterate over a list of employees and want them to set a priority flag if they live in a city which is in a country with a certain hazard level of 5 or higher.
I'd love to go the stream way as above, but can't find a way to do it. I "am not allowed" to stream my way down the city, country, hazardlevel and possible further, as ultimatively I need my employee object I began with, to set the flag on him.
I only know Java, so I don't even know if this would actually be possible in other, possibly more functional, programming languages.
I could use the following code as a workaround, but it would be nicer to a cleaner way:
List<Employee> employees = [...];
employees.stream()
.forEach(employee -> {
Optional<Integer> lvl = Optional.of(employee)
.map(Employee::getCity)
.map(City::getCountry)
.map(countryService::determineHazardLevel)
.filter(level -> level > 5); // integer
lvl.ifPresent(employee.setPriority(HIGH));
}
Maybe I just got it all just wrong and need to look at it completely different ...
PS: I just wrote this stuff in notepad, not sure if I made some mistakes but I hope the idea comes around. Simply put, I see it like this: Normal streams are commands like A, B, C, D
. But what I want to do is A, B, B1, B2, B3, C, D
.
But after going down the B road, I can't go back on my "main stream".
Upvotes: 3
Views: 724
Reputation: 298559
The simplest solution is to chain method calls, just like in Kayaman’s answer.
employees.stream()
.filter( employee -> employee.getCity().getCountry().determineHazardLevel() > 5).
.forEach(employee -> employee.setPriority(HIGH))
Alternatively, you can use the stream steps in an inner operation:
employees.stream()
.filter( employee -> Stream.of(employee)
.map(Employee::getCity)
.map(City::getCountry)
.mapToInt(countryService::determineHazardLevel)
.anyMatch(level -> level > 5))
.forEach(employee -> employee.setPriority(HIGH))
But for a simple chain of map
steps, I’d stay with a chain of ordinary method invocations.
Upvotes: 7
Reputation: 73578
No, as the stream is changing from Stream<Employee>
to Stream<Integer>
through the map()
operations (after all, that's what map()
is supposed to do, and there's no unmap()
).
You could only do it with
employees.stream().
filter(e -> e.getCity().getCountry().determineHazardLevel() > 5).
forEach(...)
which is ugly, but keeps the original Stream<Employee>
. For "less ugly" code, implement determineHazardLevel()
in Employee
as well.
Upvotes: 4