Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter and map a java stream at the same time

I have a list of strings, each of which is represents a date. I'd like to map this list into a list of DateTime objects; however, if any of the strings are invalid (throws an exception) I'd like to log an error but not add it to the final List. Is there a way to do both the filtering and mapping at the same time?

This is what I currently have:

List<String> dateStrs = ...;
dateStrs.stream().filter(s -> {
    try {
        dateTimeFormatter.parseDateTime(s);
        return true;
    } catch (Exception e) {
        log.error("Illegal format");
        return false;
    }
}.map(s -> {
    return dateTimeFormatter.parseDateTime(s);
}.collect(...);

Is there any way to do this so that I don't have to parseDateTime twice for each element?

Thanks

like image 427
Nosrettap Avatar asked Apr 27 '16 18:04

Nosrettap


People also ask

Can we use filter and map together in Java?

All you need is a mapping function to convert one object to another, and the map() function will do the transformation for you. It is also an intermediate stream operation which means you can call other Stream methods like a filter or collect on this to create a chain of transformation.

Can we use stream with map in Java?

Converting complete Map<Key, Value> into Stream: This can be done with the help of Map. entrySet() method which returns a Set view of the mappings contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.

What is the difference between filter and map in Java streams?

Filter takes a predicate as an argument so basically you are validating your input/collection against a condition, whereas a map allows you to define or use a existing function on the stream eg you can apply String. toUpperCase(...) etc. and transform your inputlist accordingly.

Can we have multiple filter in stream Java?

The Stream API allows chaining multiple filters. We can leverage this to satisfy the complex filtering criteria described. Besides, we can use the not Predicate if we want to negate conditions.


1 Answers

To my opinion, it would be more idiomatically correct to use flatMap here:

dateStrs.stream().flatMap(s -> {
    try {
        return Stream.of(dateTimeFormatter.parseDateTime(s));
    } catch (Exception e) {
        return Stream.empty();
    }
}).collect(...);

Here you can do everything in single operation.

like image 96
Tagir Valeev Avatar answered Nov 18 '22 12:11

Tagir Valeev