List<String> list =
Arrays.asList("TEST1", "TEST2", "TEST3");
final String finalStr =
Optional.ofNullable(list.stream()
.filter(s -> s.contains("pattern:a:b:"))
.map(str -> str.substring(str.lastIndexOf(':') + 1))
.findFirst())
.orElse(list.stream()
.filter(s -> !s.contains("pattern:c:d:"))
.findFirst())
.orElseThrow();
It will work if the list contains pattern:a:b: but for above example always throw an exception if that pattern is not available. In the orElse part it doesnt even seem to be executing.
My result is [java] => java.util.NoSuchElementException: No value present when i am epecting to return me the first element.
Edit: I wish to first find if any string with pattern:a:b exists in the list, if it does not, i wish it to return me the first string that does not contain the pattern:c:d For example
"pattern:a:b:TEST1", "pattern:c:d:TEST2", "TEST3" should always return TEST1.
"pattern:c:d:TEST1", "TEST2", "TEST3" should always return TEST2.
"TEST1", "TEST2", "TEST3" should always return TEST1.
Let's follow the evaluation. Since the inner part of the Optional.ofNullable(...)
results in Optional<String>
, the entire chain wraps it in Optional<Optional<String>>
.
After evaluation of the parameter in Optional.ofNullable(...)
, the result is roughly this:
Optional.ofNullable(Optional.<String>empty()) // Optional<Optional<String>>
.orElse(list.stream().findFirst()) // Optional<String>
.orElseThrow(); // String
The orElse
is not called as long as the Optional.empty()
is not null
, hence the outer Optional
is not empty. The flow continues with the inner Optional.enpty
on which the orElseThrow
is called and always fails by throwing java.util.NoSuchElementException
.
What you want to do is this:
final String finalStr = list.stream() // Stream<String>
.filter(s -> s.contains("pattern:a:b:")) // Stream<String>
.map(str -> str.substring(str.lastIndexOf(':') + 1)) // Stream<String>
.findFirst() // Optional<String>
.or(() -> list.stream().findFirst()) // Optional<String>
.orElseThrow(); // String
The or
method is the key one as on empty Optional<T>
it supplies with a different one without losing the Optional<T>
context.