I get message with message-headers. See sample message below
private static String sampleMessage() {
return """
message from arunmantics.com
X-Origination-IP:19.1.1.1.1
X-api-kEY=134SDGFSDG234234SDFSDF
Your order 6798977 is delivered.
This order's cost is
""";
}
I have to process this string only if it starts with message from arunmantics.com
. I am able to achieve this in imperative style. See sample code below
public static void main(String[] args) {
String message = sampleMessage();
StringBuilder sb = new StringBuilder();
if (message.startsWith("message from arunmantics.com")) {
var beginIndex = message.indexOf("com")+3;
message = message.substring(beginIndex,message.length());
for (String currentLine : message.split(System.lineSeparator())) {
if (!currentLine.startsWith("X-")) {
sb.append(currentLine);
}
}
}
System.out.println(sb);
}
But I would like to come out of this imperative coding style and move to Functional style.
I would like to do something like this
message.lines()
.filter(...)
But i could't exactly make a decision to stop the stream if it is not starting with message from arunmantics.com
.
I used findFirst()
, but as expected it gives me an Optional with that particular string alone and filters out rest of the strings.
Is this not achievable at all using Streams API ?
You can still check whether the string starts with "message from arunmantics.com" the same you did before. There's nothing "non-functional" about it.
I was looking to have it as part of the stream pipeline
If you really want to do this as a chain, you could technically create a singleton stream, use a filter
to essentially create an empty stream if the message doesn't start with "message from arunmantics.com", and then flatMap
to the lines
.
var result = Stream.of(message)
.filter(s -> s.startsWith("message from arunmantics.com"))
// the above creates an empty stream if the condition is false
// and everything below will effectively do nothing, and the result will be an empty string
.flatMap(String::lines)
.skip(1) // skips the "message from..." line
.filter(x -> !x.startsWith("X-"))
.collect(Collectors.joining());
This really doesn't show the intent as clearly as using an if
, and it's really not any better than just using an if
, in my opinion.