I have the following interface with two implementations:
public interface Parser { void parse(); boolean canParse(String message); } class StackParser implements Parser { public void parse(){ System.out.println("Parsing stackoverflow"); } public boolean canParse(String message){ return message.equals("stackoverflow"); } } class YoutubeParser implements Parser { public void parse() { System.out.println("Parsing youtube"); } public boolean canParse(String message) { return message.equals("youtube"); } }
I go to check incoming message and parse "stackoverflow"
or "youtube"
:
public class Main { private List<Parser> parsers; public static void main(String[] args) { new Main().doSomething("youtube"); } void doSomething(String message){ parsers.stream() .filter(p -> p.canParse(message)) .forEach(p -> p.parse()); } }
Okay, pretty good. But what if message is not "stackoverflow"
or "youtube"
? App will be silent, but I want to send another default message if no matches were found, like "I can't parse this web!"
.
I know that will not works (even compile), but it's also should print "I can't parse this web"
only one time, not for every false
condition.
parsers.stream() .filter(p -> { if (p.canParse(message) == false) { System.out.println("I can't parse it!"); } }) .forEach(p -> p.parse());
How can I do it?
Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.
Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.
One Line if-else Statement Using filter in Java 8The streams filter method takes a Predicate and behaves like if-else in Java language. The above program instantiates a list using Arrays. asList() method.
Conventional if/else Logic Within forEach() First of all, let's create an Integer List and then use conventional if/else logic within the Integer stream forEach() method: List<Integer> ints = Arrays. asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); ints. stream() .
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With