This question already has an answer here:
-
How to use if-else logic in Java 8 stream forEach
4 answers
Scenario: There is a situation where I need to set some values to List
of objects based on some field condition using the Java 8 streams API.
Below is the sample of object User
.
public class User{
private int id;
private String name;
private String text;
private boolean isActive;
}
Here is the code I have worked out
List<User> users = userDao.getAllByCompanyId(companyId);
users.stream()
.filter(Objects::nonNull)
.filter(User::isActive)
.peek(user -> user.setText('ABC'))
.filter(user -> !user.isActive())
.peek(user -> user.setText('XYZ')
I know that the way I have written to set the values to object based on condition is wrong.
This is just a try-out using stream, at the end I need to set values to users
object.
Is there any way to handle if-else condition.
Perhaps you are overcomplicating this.
List<User> users = new ArrayList<>();
users.stream()
.filter(Objects::nonNull)
.forEach(u -> u.setRole(u.isActive()?"ABC":"XYZ"));
I am guessing the desired behavior, please correct me if I'm wrong.
You can use a block inside lambda expressions:
List<User> users = userDao.getAllByCompanyId(companyId);
users.stream().filter(Objects::nonNull).forEach(user -> {
if (user.isPresent()) {
user.setRole("ABC");
} else {
user.setRole("XYZ");
}
});
You can't do what you want by using another filter
operation with the negated condition, as this will make you end up with an empty stream (i.e. if from a list of numbers you remove elements < 5 and then you remove elements >= 5, you'll end up with an empty list).
The most straightforward and clean way to achieve what you want is to use forEach
as in the other answers, especially for a simple case such as this one (which consists of calling the same setter method with its argument being either ABC
or XYZ
, based on the condition).
But in case you need to apply different logic to each element, based on some condition, it might be worth partitioning your stream by this condition, and then act differently on each partition:
Map<Boolean, List<User>> partitioned = users.stream()
.filter(Objects::nonNull)
.collect(Collectors.partitioningBy(User::isActive));
Then, simply act on each partition:
// Apply logic to active users partition
partitioned.get(true).forEach(u -> u.setText("ABC"));
// Apply logic to inactive users partition
partitioned.get(false).forEach(u -> u.setText("XYZ"));