Just put the condition into the lambda itself, e.g.
animalMap.entrySet().stream()
.forEach(
pair -> {
if (pair.getValue() != null) {
myMap.put(pair.getKey(), pair.getValue());
} else {
myList.add(pair.getKey());
}
}
);
This can be simplified and made more readable using Map.forEach, as suggested by Jorn Vernee:
animalMap.forEach(
(key, value) -> {
if (value != null) {
myMap.put(key, value);
} else {
myList.add(key);
}
}
);
Of course, these solutions assume that both collections (myMap and myList) are declared and initialized prior to the above pieces of code.
Just put the condition into the lambda itself, e.g.
animalMap.entrySet().stream()
.forEach(
pair -> {
if (pair.getValue() != null) {
myMap.put(pair.getKey(), pair.getValue());
} else {
myList.add(pair.getKey());
}
}
);
This can be simplified and made more readable using Map.forEach, as suggested by Jorn Vernee:
animalMap.forEach(
(key, value) -> {
if (value != null) {
myMap.put(key, value);
} else {
myList.add(key);
}
}
);
Of course, these solutions assume that both collections (myMap and myList) are declared and initialized prior to the above pieces of code.
In most cases, when you find yourself using forEach on a Stream, you should rethink whether you are using the right tool for your job or whether you are using it the right way.
Generally, you should look for an appropriate terminal operation doing what you want to achieve or for an appropriate Collector. Now, there are Collectors for producing Maps and Lists, but no out of-the-box collector for combining two different collectors, based on a predicate.
Now, this answer contains a collector for combining two collectors. Using this collector, you can achieve the task as
Pair<Map<KeyType, Animal>, List<KeyType>> pair = animalMap.entrySet().stream()
.collect(conditional(entry -> entry.getValue() != null,
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue),
Collectors.mapping(Map.Entry::getKey, Collectors.toList()) ));
Map<KeyType,Animal> myMap = pair.a;
List<KeyType> myList = pair.b;
But maybe, you can solve this specific task in a simpler way. One of you results matches the input type; it’s the same map just stripped off the entries which map to null. If your original map is mutable and you don’t need it afterwards, you can just collect the list and remove these keys from the original map as they are mutually exclusive:
List<KeyType> myList=animalMap.entrySet().stream()
.filter(pair -> pair.getValue() == null)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
animalMap.keySet().removeAll(myList);
Note that you can remove mappings to null even without having the list of the other keys:
animalMap.values().removeIf(Objects::isNull);
or
animalMap.values().removeAll(Collections.singleton(null));
If you can’t (or don’t want to) modify the original map, there is still a solution without a custom collector. As hinted in Alexis C.’s answer, partitioningBy is going into the right direction, but you may simplify it:
Map<Boolean,Map<KeyType,Animal>> tmp = animalMap.entrySet().stream()
.collect(Collectors.partitioningBy(pair -> pair.getValue() != null,
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
Map<KeyType,Animal> myMap = tmp.get(true);
List<KeyType> myList = new ArrayList<>(tmp.get(false).keySet());
The bottom line is, don’t forget about ordinary Collection operations, you don’t have to do everything with the new Stream API.
You can do something like this:
if(returnOptional().isPresent) {
List<Object> list = db.findAllById(id);
list.stream().map(object -> {
if(/*predicate logic*/) {
// perform function if predicate logic true
}
else {
// perform function if predicate logic false
}
return object;
});
}
but as philip mentioned technically you cannot split a stream into two streams and collect.
Optional.ofNullable(list).ifPresent( y -> {
if (y.stream().anyMatch(x -> /*predicate*/)) {
System.out.println("a");
} else {
System.out.println("b");
}
});
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");
}
});
There is no if/else in Java streams. Use Stream.map to remove the dot if the name contains a dot as first letter and then just join using Collectors.join(".")
String result = Stream.of(student.getFirstName(), student.getLastName())
.filter(Objects::nonNull)
.map(name -> name.endsWith(".") ? name.substring(0, name.length() - 1) : name)
.collect(Collectors.joining(". "));
You can use String.replace():
String firstName = student.getFirstName().replace('.', '');
Though I'm not sure why you need to use a Stream in your scenario, you could simply just do:
String result = student.getFirstName().replace('.', '') + "." + student.getLastName();
Or something similar.
This is a perfect example of when to use the Optional#orElse or the Optional#orElseThrow method(s). You want to check if some condition is met so you filter, trying to return a single result. If one does not exist, some other condition is true and should be returned.
try {
Parser parser = parsers.stream()
.filter(p -> p.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
In case only one parser can parse the message at a time you could add a default parser:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
And then use it via
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
or alternatively drop the DefaultParser and just do
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}
If at least one of the values is guaranteed, you could refactor it like this:
public List<UserAction> getUserActionList(Map<String, String> map) {
return Stream.of("userid", "username", "userrole")
.map(map::get)
.filter(s -> !checkForNullEmpty(s))
.limit(1)
.map(output -> new UserAction(map, output))
.collect(Collectors.toList());
}
If it is not guaranteed that at least one value will be non-null, it's a little uglier, but not too bad:
public List<UserAction> getUserActionList(Map<String, String> map) {
return Stream.of("userid", "username", "userrole")
.map(map::get)
.filter(s -> !checkForNullEmpty(s))
.limit(1)
.map(output -> new UserAction(map, output))
.map(Collections::singletonList)
.findFirst()
.orElseGet(() -> Arrays.asList(new UserAction(map, null)));
}
It's not really clear about the task you need to accomplish, but in general, everything that you need to write in your if statements you can do with filter() method from Stream API. Then, in map() method you'd have the exact logic which is needed to be done with the data (e.g. transforming it to some other type or getting values which are needed). collect() method is used to create a result from the Stream, e.g. list, set, map, single object or anything else. For example:
map.entrySet().stream()
.filter(e -> {
// filter the data here, so if isStrOrInt or containsUserData is false - we will not have it in map() method
boolean isStrOrInt = e.getValue() instanceof String || e.getValue() instanceof Integer;
boolean containsUserData = e.getKey().contains("userrole") || e.getKey().contains("userid") || e.getKey().contains("username");
return isStrOrInt && containsUserData;
})
.map(e -> {
if (e.getKey().contains("userrole")) {
// do something
}
// some more logic here
return e.getValue();
})
.collect(Collectors.toList());
// or e.g. .reduce((value1, value2) -> value1 + value2);
If you need to create a single object in the end, you would probably need reduce() method. I recommend you to check reduction operations, general information about Stream API to understand how they work.