There is not a very much better way of doing it than you have it - it might be nicer if you extracted it to a method, but that's really it.

Another way might be to construct Optionals from all values, and then use Optional.filter to map empty values to empty optionals:

yearStreams.map(Optional::of)
           .map(opt -> opt.filter(Predicate.not(String::isEmpty)));

Is this better? Probably not.

Yet another way would be to make use of something like Guava's Strings.emptyToNull (other libraries are available), which turns your empty strings into null first; and then use Optional.ofNullable to turn non-nulls and nulls into non-empty and empty Optionals, respectively:

yearStreams.map(Strings::emptyToNull)
           .map(Optional::ofNullable)
Answer from Andy Turner on Stack Overflow
Top answer
1 of 5
122

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.

2 of 5
18

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.

🌐
Baeldung
baeldung.com › home › java › java streams › how to use if/else logic in java streams
How to Use if/else Logic in Java Streams | Baeldung
May 28, 2024 - The partitioningBy() method returns a Map that stores Boolean as keys and List as values. Here, the list associated with the key “true” contains all elements matching the given predicate, which denotes even integers. On the other hand, the key “false” points to the list that represent odd integers. In this quick article, we’ve explored how to create a Java 8 Stream and how to implement if/else logic using the forEach() method.
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › using ‘if-else’ conditions with java streams
Using 'if-else' Conditions with Java Streams - HowToDoInJava
March 3, 2022 - Arrays.asList(-1, 1, -2, 3, 4, -5, 6, 0).stream() .forEach( i -> { if (i == 0) { System.out.println("Number is 0"); } else if (i > 0) { System.out.println("Positive Number"); } else { System.out.println("Negative Number"); } } ); If we intend to apply only 'if' logic then we can pass the condition directly do the filter() function as a Predicate.
🌐
Shootskill
shootskill.com › java8 › stream-if-else-logic
Shootskill
We cannot provide a description for this page right now
🌐
Javaprogramto
javaprogramto.com › 2021 › 12 › java-8-streams-if-else.html
Java 8 Streams if else logic JavaProgramTo.com
December 11, 2021 - Use the java 8 stream filter() method to get the equivalent functionality of the traditional if condition. ... The Predicate is the functional interface that does the job of if condition.
Find elsewhere
🌐
Medium
medium.com › @mohitbajaj1995 › how-to-use-if-else-logic-in-java-streams-10-practical-approaches-956ca65ade3c
How to use If/else Logic in Java Streams: 10 Practical Approaches | by Mohit Bajaj | Medium
March 6, 2025 - This is the simplest way to start — just put your if/else logic directly inside forEach(): List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); numbers.stream() .forEach(num -> { if (num % 2 == 0) { System.out.println(num ...
🌐
Medium
medium.com › @prawin609 › replacing-nested-if-else-null-checks-with-optional-map-and-filter-in-java-streams-api-6d831fbd81ca
Replacing Nested If-Else Null Checks with Optional, Map, and Filter in Java Streams API | by Prawin Thangaswamy | Medium
September 8, 2024 - Optional Wrapping: Each order is wrapped in an Optional to handle potential null values without interrupting the stream. Nested Mapping and Filtering: i. The Optional chain extracts the Customer, Address, and ZipCode. ii. Only zip codes that start with “1” are allowed through. Transformation: The zip codes are formatted to a specific string pattern. Default Handling: If any value in the chain is null, a default message is provided.
🌐
Coderanch
coderanch.com › t › 649697 › java › Java-streams-Filter
Java 8 streams - Filter if else not (Features new in Java 8 forum at Coderanch)
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums · this forum made possible by our volunteer staff, including ... ... Hi, I'm trying to figure out if there's a more elegant way of doing this with streams rather than checking separately through an if-else statement?
Top answer
1 of 5
5

You can use

public ShapeType resolveShapeType(final List<Shape> shapes) {
    int sides = shapes.stream()
        .mapToInt(Shape::getSideCount)
        .filter(count -> count==4 || count==6)
        .max().orElse(0);
    return sides==6? ShapeType.HEXA: sides==4? ShapeType.RECT: ShapeType.GENERIC;
}

This maps each element to its side count and reduces them to the preferred type, which happens to be the maximum count here, so no custom reduction function is needed.

This isn’t short-circuiting, but for most use cases, it will be sufficient. If you want to reduce the number of operations to the necessary minimum, things will be more complicated.

public ShapeType resolveShapeType(final List<Shape> shapes) {
    OptionalInt first = IntStream.range(0, shapes.size())
        .filter(index -> {
            int count = shapes.get(index).getSideCount();
            return count == 6 || count == 4;
        })
        .findFirst();
    if(!first.isPresent()) return ShapeType.GENERIC;
    int ix = first.getAsInt(), count = shapes.get(ix).getSideCount();
    return count==6? ShapeType.HEXA: shapes.subList(ix+1, shapes.size()).stream()
        .anyMatch(shape -> shape.getSideCount()==6)? ShapeType.HEXA: ShapeType.RECT;
}

We know that we can stop at the first HEXA, but to avoid a second pass, it’s necessary to remember whether there was an occurence of RECT for the case there is no HEXA. So this searches for the first element that is either, a RECT or HEXA. If there is none, GENERIC is returned, otherwise, if the first was not a HEXA, the remaining elements are checked for an element of the HEXA kind. Note that for processing the remainder after the first RECT, no filter is needed as it is implied that shapes that are neither, RECT nor HEXA, can’t fulfill the condition.

But it should also be obvious that this code, trying to minimize the numbers of checks, is harder to read than an equivalent for loop.

2 of 5
4

Assuming that only the three types of shapes can be present in the list, an alternative would be:

Set<Integer> sides = shapes.stream()
      .map(Shape::getSideCount)
      .collect(toSet());

if (sides.contains(6)) return HEXA;
else if (sides.contains(4)) return RECTANGLE;
else return GENERIC;

But I think the most straightforward (and efficient) way would be a good old for loop:

ShapeType st = GENERIC;
for (Shape s : shapes) {
  if (s.getSideCount() == 6) return HEXA;
  if (s.getSideCount() == 4) st = RECTANGLE;
}
return st;
🌐
CodingTechRoom
codingtechroom.com › tutorial › java-java-8-streams-if-else-logic
Mastering Java 8 Streams: Implementing If-Else Logic Effectively - CodingTechRoom
Java 8 introduced Streams, a powerful abstraction for working with sequences of data in a functional style. With Streams, you can process data collections in a concise way, including the ability to implement conditional logic such as if-else.