Possibility of getOrElseReturn in Kotlin - java

I often have a problem with Optional and similar classes Option, Try, Either from VAVR for example.
Let's say I have some Optional, and if it's empty I want to immediately return from a method (without exception, since my method is returning Optional aswell, so getOrElseThrow is out of the picture) and if it's present I want to further process it.
public Optional<Integer> converter() {
Optional<String> opt = getSomething();
if(!opt.isPresent())
return Optional.empty();
String value = opt.get();
// some manipulations on value, such as map and flatMap would cause a huge mess
return Integer.parseInt(value);
}
I just need to return immediately in case value is empty, I can't do chain of map and flatMap. The whole pain is doing .get(). Something like getOrElseThrow, but with return instead of throw would be fantastic - getOrElseReturn. Obviously not possible in Java, so I thought about trying this in Kotlin.
fun safeOptional(): Optional<Int> {
val extracted = Optional.of("123")
.getOrElseReturn { return Optional.empty() }
val modified = extracted.toInt() * 2
return Optional.of(modified)
}
private inline fun <T> Optional<T>.getOrElseReturn(block: (Optional<T>) -> T): T {
return if (!this.isPresent)
block(this)
else
this.get()
}
Much to my surprise it actually does what I want. If I change the Optional.of("123") to Optional.empty() it immediately returns from a method. I don't understand how it compiles though.
My method needs a block: (Optional<T>) -> T, otherwise it wouldn't compile. So in my case I have Optional<String> and I need to pass a block: (Optional<String>) -> String, but hey - the block that I have is nowhere close to this and it still compiles, how?
When I extract the block to variable it becomes val block: (Optional<String>) -> Nothing (I guess return statement is Nothing) and it still compiles, surprising me even more.
btw I know this code is not strictly what I want - someone can pass another block without non-local return to the method, but I don't think there is another way

Extract the second part of your method into another private method and call getSomething().map(this::otherPrivateMethod)
It will not be invoked if no value is present in getSomething()
Basically,
public Optional<Integer> converter() {
return getSomething().map(this::privateConverter);
}
private Integer privateConverter(Integer integer) {
// some manipulations on value, such as map and flatMap would cause a huge mess
return Integer.parseInt(value);
}

Answering the Kotlin part:
fun safeOptional(): Optional<Int> {
val extracted = Optional.of("123")
.getOrElseReturn { return Optional.empty() }
.......
}
The return here is not return from a lambda, but rather a return from function safeOptional so therefore lambda doesn't return anything (it returns Nothing). Lambda returning Nothing can be passed as lambda returning anything.
To get a compile error, you should return from lambda instead:
val extracted = Optional.of("123")
.getOrElseReturn { return#getOrElseReturn Optional.empty() }
Generally, Optional are not needed in Kotlin. You should use nullable types instead. You would combine them with nullsafe operators (e.g. the Elvis operator -- ?::
fun nullsafe(x: String?): Optional<Int> {
val extracted = x ?: return Optional.empty()
val modified = extracted.toInt() * 2
return Optional.of(modified)
}
nullsafe("2") // => Optional[4]
nullsafe(null) // => Optional.empty

Related

How to get Different Optional type of Object from CompletableFuture

I have one code snippet, which is calling 2 different services based on some a if condition. And both the services return CompletableFuture<Optional<SomeObject>>. Following is the code logic looks like
if(someCondition){
CompletableFuture<Optional<SomeObjectType1>> = service1.call();
}else{
CompletableFuture<Optional<SomeObjectType2>> = service2.call();
}
And both SomeObjectType1 and SomeObjectType2 have a String inside it, which is of my interest. My current code looks like this:
private ContentWrapper getContentWrapper(input1, input2, ....) {
String content = null;
if (some_condition is true) {
List<Object_Type_1> list = service1.fetchTheCompletableFuture(..... inputs...)
.join()
.map(ListOutput::getList)
.orElse(null);
if (CollectionUtils.isNotEmpty(list)) {
content = list.get(0).getContent();
}
} else {
content = service2
.fetchTheCompletableFuture(..... inputs...)
.join()
.map(RenderedContent::getContent)
.orElse(null);
}
return content != null ? new ContentWrapper(content) : null;
}
Now my question is, can this if-else clause be removed or make it more clear by using lambdas. I am new in lambdas and does not have very good idea on this.
I am not sure whether the code below even compiles due to the vagueness.
private ContentWrapper getContentWrapper(input1, input2, ....) {
Optional<RenderedContent> content = some_condition
? service1
.fetchTheCompletableFuture(..... inputs...)
.join()
.map(ListOutput::getList)
.stream()
.findFirst()
: service2
.fetchTheCompletableFuture(..... inputs...)
.join();
}
return content
.map(RenderedContent::getContent)
.map(ContentWrapper::new).orElse(null);
}
The first service seems to yield a list of RenderedContent of which to take the first if there is one.
The second service may yield a Rendered content immediately.
So you can join the if-else to an Optional<RenderedContent>.
The map(RenderedContent::getContent) will yield Optional.empty() if it was empty to begin with. Otherwise getContent is called and wrapped in an Optional.
If present new ContentWrapper(...) might be called.
Notice much may fail, like getContent returning null (though there is an Optional.ofNullable.
Nevertheless Streams may be very expressive.
I would avoid using null in favor of Optional as that plays better together.

What's the advantage of Optional.ofNullable(itemKey) over itemKey == null

I was just wondering when do we need to choose Optional over if else or nested null check. say for example is there any advantage of one another below or do you think the Optional could be an overkill
String.valueOf(Optional.ofNullable(itemKey).map(ItemKey::getId).orElse(null));
vs
String.valueOf(itemKey == null ? null : itemKey.getId());
I always keen to use the Optional.of or Optional.ofNullable when I had to pick nested item of a given object like below,
private String formatCurrency(String symbol, BigDecimal value) {
return Optional.ofNullable(value)
.map(BigDecimal::doubleValue)
.map(Object::toString)
.map(val -> symbol + val.replaceAll(REGEX_REMOVE_TRAILING_ZEROS, "$2"))
.orElse("");
}
Can I please know where in the code the Optional is absolutely unnecessary.
If you already have itemKey in your code, there is no meaning of transforming it to an Optional, it just makes the code more complex. However, if you want to use optionals, I think it'd be more appropriate to do something like this:
public Optional<ItemKey> getItemKey() {
if (...) {
return Optional.of(new ItemKey());
}
return Optional.empty()
}
public void mainCode() {
String id = getItemKey().map(ItemKey::getId).orElse(null);
}

rxjava2 - if else on Maybe

I am looking for what is the recommended practice in rxjava2 to handle a case where one flowable leads to conditional behaviors.
More concretely, I have a Maybe<String> for which I want to Update the String on the database if the String exists or, if it doesn't exists I want to create a new String and save it on the database.
I thought of the below but obviously it is not what I am looking for:
Maybe<String> source = Maybe.just(new String("foo")); //oversimplified source
source.switchIfEmpty(Maybe.just(new String("bar"))).subscribe(result ->
System.out.println("save to database "+result));
source.subscribe(result -> System.out.println("update result "+result));
The above obviously produces
save to database foo
update result foo
I tried also the below which gives the expected result but still feel it's... weird.
Maybe<String> source = Maybe.just(new String("foo")); //oversimplified source
source.switchIfEmpty(Maybe.just(new String("bar")).doOnSuccess(result ->
System.out.println("save to database "+result))).subscribe();
source.doOnSuccess(result -> System.out.println("update result "+result)).subscribe();
How can I have an action for when the result exists and when it doesn't exists? How is that use case supposed to be handled in rxjava2?
Update 01
I tried the below and it looks cleaner than what I came up with above. Note sure it is recommended rxjava2 practice however...
Maybe.just(new String("foo"))
.map(value -> Optional.of(value))
.defaultIfEmpty(Optional.empty())
.subscribe(result -> {
if(result.isPresent()) {
System.out.println("update result "+result);
}
else {
System.out.println("save to database "+"bar");
}
});
You have the isEmpty() operator that will return you Boolean if the Maybe source is empty or not, and then you can flatMap it and write a if else statement depending on that Boolean
This is a common pattern in our code as well, though in our case the choices are themselves async. You can't get quite the right semantic by simply composing flatMapX and switchIfEmpty (in either order), so I am curious why this isn't part of the API.
Here's what we're doing for now (this example for when the 2 options are both Completables, we have similar things for the other types as well):
public static <T> Completable flatMapCompletable(Maybe<T> target,
#ClosureParams(FirstParam.FirstGenericType.class)
Closure<? extends CompletableSource> completableSupplier,
Supplier<CompletableSource> emptySupplier) {
Maybe<T> result = target.cache();
return result.isEmpty().flatMapCompletable(empty -> {
if (empty) {
return emptySupplier.get();
} else {
return result.flatMapCompletable(completableSupplier::call);
}
});
}
We're using Groovy, so we package these up as extension methods. I'm not thrilled with the need to use cache() so I'm wondering if there is a better alternative. From looking at the code, an operator which basically combines flatMapX and switch looks like it wouldn't be too hard (but I feel like I'm missing something).
Try something like this. checkDB can return a Maybe or Single or whatever which emits either an optional or a wrapper Object.
checkDB(String)
.flatMap(s -> {
if (s.isPresent()) {
return updateDB(s.get());
} else {
return insertDB("new String");
}
})
There is an solution using the flatMap call with 3 params
fun addOrUpdate(message: LocalMessage): Single<LocalMessage> {
return getById(message.id) // returns Maybe
.flatMap(
Function {
update(message) // onSuccess update call returns Single
},
Function {
Single.error(it) // onError
},
Callable {
add(message) // onComplete add call returns Single
}
)
}
}
Or shorter version
fun addOrUpdate(message: LocalMessage): Single<LocalMessage> {
return getById(message.id) // returns Maybe
.flatMap(
{
update(message) // onSuccess update call returns Single
},
{
Single.error(it) // onError
},
{
add(message) // onComplete add call returns Single
}
)
}
}

How to use orElse when you need to invoke a method on the result?

I have the following code blow. I tried finding a way to avoid the if (something.isPresent()) row and declaring the Optional<Something> something as well. Instead I'd like to chain the Optional.orElse() method and return the result directly. But I can't seem to find a way, since the method needs to return null in case the element wasn't found, and if it was found, it needs to call a method on it before returning.
Is there a better way to do it?
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class OrElseWhat {
private class Something {
private String it;
Something(String it) { this.it = it; }
String getIt() { return it; }
}
private List<Something> somethings = new ArrayList<Something>() {
{
add(new Something("one"));
add(new Something("two"));
add(new Something("three"));
}
};
public String getFourOrNull() {
Optional<Something> something = somethings.stream()
.filter(s -> s.getIt().equals("four"))
.findAny();
if (something.isPresent()) {
return something.get().getIt();
}
return null;
}
}
You may call the method while your value is still in Optional form using map:
public String getFourOrNull() {
return somethings.stream()
.filter(s -> s.getIt().equals("four"))
.findAny()
.map(Something::getIt)
.orElse(null);
}
From maps's documentation:
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
That said, if you can, listen to #Aaron and drop the orElse so that getFourOrNull returns the Optional. No method should ever return null in a code base where Optional is used.
I think you should rather change the signature of your method to Optional<String> and always return something.
Optional were made for this kind of case : they make it possible to avoid returning some non-specific value (maybe it's null ? or "" ? or -1) and rather plainly describe starting from your signature that maybe you'll be able to return some type, but not always.

Using Java 8's Optional with Stream::flatMap

The new Java 8 stream framework and friends make for some very concise Java code, but I have come across a seemingly-simple situation that is tricky to do concisely.
Consider a List<Thing> things and method Optional<Other> resolve(Thing thing). I want to map the Things to Optional<Other>s and get the first Other.
The obvious solution would be to use things.stream().flatMap(this::resolve).findFirst(), but flatMap requires that you return a stream, and Optional doesn't have a stream() method (or is it a Collection or provide a method to convert it to or view it as a Collection).
The best I can come up with is this:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
But that seems awfully long-winded for what seems like a very common case.
Anyone have a better idea?
Java 9
Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();
Java 8
Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();
Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.
I'm adding this second answer based on a proposed edit by user srborlongan to my other answer. I think the technique proposed was interesting, but it wasn't really suitable as an edit to my answer. Others agreed and the proposed edit was voted down. (I wasn't one of the voters.) The technique has merit, though. It would have been best if srborlongan had posted his/her own answer. This hasn't happened yet, and I didn't want the technique to be lost in the mists of the StackOverflow rejected edit history, so I decided to surface it as a separate answer myself.
Basically the technique is to use some of the Optional methods in a clever way to avoid having to use a ternary operator (? :) or an if/else statement.
My inline example would be rewritten this way:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
An my example that uses a helper method would be rewritten this way:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
return opt.map(Stream::of)
.orElseGet(Stream::empty);
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
COMMENTARY
Let's compare the original vs modified versions directly:
// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
The original is a straightforward if workmanlike approach: we get an Optional<Other>; if it has a value, we return a stream containing that value, and if it has no value, we return an empty stream. Pretty simple and easy to explain.
The modification is clever and has the advantage that it avoids conditionals. (I know that some people dislike the ternary operator. If misused it can indeed make code hard to understand.) However, sometimes things can be too clever. The modified code also starts off with an Optional<Other>. Then it calls Optional.map which is defined as follows:
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
The map(Stream::of) call returns an Optional<Stream<Other>>. If a value was present in the input Optional, the returned Optional contains a Stream that contains the single Other result. But if the value was not present, the result is an empty Optional.
Next, the call to orElseGet(Stream::empty) returns a value of type Stream<Other>. If its input value is present, it gets the value, which is the single-element Stream<Other>. Otherwise (if the input value is absent) it returns an empty Stream<Other>. So the result is correct, the same as the original conditional code.
In the comments discussing on my answer, regarding the rejected edit, I had described this technique as "more concise but also more obscure". I stand by this. It took me a while to figure out what it was doing, and it also took me a while to write up the above description of what it was doing. The key subtlety is the transformation from Optional<Other> to Optional<Stream<Other>>. Once you grok this it makes sense, but it wasn't obvious to me.
I'll acknowledge, though, that things that are initially obscure can become idiomatic over time. It might be that this technique ends up being the best way in practice, at least until Optional.stream gets added (if it ever does).
UPDATE: Optional.stream has been added to JDK 9.
You cannot do it more concise as you are already doing.
You claim that you do not want .filter(Optional::isPresent) and .map(Optional::get).
This has been resolved by the method #StuartMarks describes, however as a result you now map it to an Optional<T>, so now you need to use .flatMap(this::streamopt) and a get() in the end.
So it still consists of two statements and you can now get exceptions with the new method! Because, what if every optional is empty? Then the findFirst() will return an empty optional and your get() will fail!
So what you have:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
is actually the best way to accomplish what you want, and that is you want to save the result as a T, not as an Optional<T>.
I took the liberty of creating a CustomOptional<T> class that wraps the Optional<T> and provides an extra method, flatStream(). Note that you cannot extend Optional<T>:
class CustomOptional<T> {
private final Optional<T> optional;
private CustomOptional() {
this.optional = Optional.empty();
}
private CustomOptional(final T value) {
this.optional = Optional.of(value);
}
private CustomOptional(final Optional<T> optional) {
this.optional = optional;
}
public Optional<T> getOptional() {
return optional;
}
public static <T> CustomOptional<T> empty() {
return new CustomOptional<>();
}
public static <T> CustomOptional<T> of(final T value) {
return new CustomOptional<>(value);
}
public static <T> CustomOptional<T> ofNullable(final T value) {
return (value == null) ? empty() : of(value);
}
public T get() {
return optional.get();
}
public boolean isPresent() {
return optional.isPresent();
}
public void ifPresent(final Consumer<? super T> consumer) {
optional.ifPresent(consumer);
}
public CustomOptional<T> filter(final Predicate<? super T> predicate) {
return new CustomOptional<>(optional.filter(predicate));
}
public <U> CustomOptional<U> map(final Function<? super T, ? extends U> mapper) {
return new CustomOptional<>(optional.map(mapper));
}
public <U> CustomOptional<U> flatMap(final Function<? super T, ? extends CustomOptional<U>> mapper) {
return new CustomOptional<>(optional.flatMap(mapper.andThen(cu -> cu.getOptional())));
}
public T orElse(final T other) {
return optional.orElse(other);
}
public T orElseGet(final Supplier<? extends T> other) {
return optional.orElseGet(other);
}
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSuppier) throws X {
return optional.orElseThrow(exceptionSuppier);
}
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
#Override
public boolean equals(final Object obj) {
return optional.equals(obj);
}
#Override
public int hashCode() {
return optional.hashCode();
}
#Override
public String toString() {
return optional.toString();
}
}
You will see that I added flatStream(), as here:
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
Used as:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.flatMap(CustomOptional::flatStream)
.findFirst()
.get();
You still will need to return a Stream<T> here, as you cannot return T, because if !optional.isPresent(), then T == null if you declare it such, but then your .flatMap(CustomOptional::flatStream) would attempt to add null to a stream and that is not possible.
As example:
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
Used as:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.map(CustomOptional::getTOrNull)
.findFirst()
.get();
Will now throw a NullPointerException inside the stream operations.
Conclusion
The method you used, is actually the best method.
A slightly shorter version using reduce:
things.stream()
.map(this::resolve)
.reduce(Optional.empty(), (a, b) -> a.isPresent() ? a : b );
You could also move the reduce function to a static utility method and then it becomes:
.reduce(Optional.empty(), Util::firstPresent );
As my previous answer appeared not to be very popular, I will give this another go.
A short answer:
You are mostly on a right track. The shortest code to get to your desired output I could come up with is this:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.findFirst()
.flatMap( Function.identity() );
This will fit all your requirements:
It will find first response that resolves to a nonempty Optional<Result>
It calls this::resolve lazily as needed
this::resolve will not be called after first non-empty result
It will return Optional<Result>
Longer answer
The only modification compared to OP initial version was that I removed .map(Optional::get) before call to .findFirst() and added .flatMap(o -> o) as the last call in the chain.
This has a nice effect of getting rid of the double-Optional, whenever stream finds an actual result.
You can't really go any shorter than this in Java.
The alternative snippet of code using the more conventional for loop technique is going to be about same number of lines of code and have more or less same order and number of operations you need to perform:
Calling this.resolve,
filtering based on Optional.isPresent
returning the result and
some way of dealing with negative result (when nothing was found)
Just to prove that my solution works as advertised, I wrote a small test program:
public class StackOverflow {
public static void main( String... args ) {
try {
final int integer = Stream.of( args )
.peek( s -> System.out.println( "Looking at " + s ) )
.map( StackOverflow::resolve )
.filter( Optional::isPresent )
.findFirst()
.flatMap( o -> o )
.orElseThrow( NoSuchElementException::new )
.intValue();
System.out.println( "First integer found is " + integer );
}
catch ( NoSuchElementException e ) {
System.out.println( "No integers provided!" );
}
}
private static Optional<Integer> resolve( String string ) {
try {
return Optional.of( Integer.valueOf( string ) );
}
catch ( NumberFormatException e )
{
System.out.println( '"' + string + '"' + " is not an integer");
return Optional.empty();
}
}
}
(It does have few extra lines for debugging and verifying that only as many calls to resolve as needed...)
Executing this on a command line, I got the following results:
$ java StackOferflow a b 3 c 4
Looking at a
"a" is not an integer
Looking at b
"b" is not an integer
Looking at 3
First integer found is 3
Late to the party, but what about
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.findFirst().get();
You can get rid of the last get() if you create a util method to convert optional to stream manually:
things.stream()
.map(this::resolve)
.flatMap(Util::optionalToStream)
.findFirst();
If you return stream right away from your resolve function, you save one more line.
I'd like to promote factory methods for creating helpers for functional APIs:
Optional<R> result = things.stream()
.flatMap(streamopt(this::resolve))
.findFirst();
The factory method:
<T, R> Function<T, Stream<R>> streamopt(Function<T, Optional<R>> f) {
return f.andThen(Optional::stream); // or the J8 alternative:
// return t -> f.apply(t).map(Stream::of).orElseGet(Stream::empty);
}
Reasoning:
As with method references in general, compared to lambda expressions, you can't accidentaly capture a variable from the accessible scope, like:
t -> streamopt(resolve(o))
It's composable, you can e.g. call Function::andThen on the factory method result:
streamopt(this::resolve).andThen(...)
Whereas in the case of a lambda, you'd need to cast it first:
((Function<T, Stream<R>>) t -> streamopt(resolve(t))).andThen(...)
If you're stuck with Java 8 but have access to Guava 21.0 or newer, you can use Streams.stream to convert an optional into a stream.
Thus, given
import com.google.common.collect.Streams;
you can write
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Streams::stream)
.findFirst();
If you don't mind to use a third party library you may use Javaslang. It is like Scala, but implemented in Java.
It comes with a complete immutable collection library that is very similar to that known from Scala. These collections replace Java's collections and Java 8's Stream. It also has its own implementation of Option.
import javaslang.collection.Stream;
import javaslang.control.Option;
Stream<Option<String>> options = Stream.of(Option.some("foo"), Option.none(), Option.some("bar"));
// = Stream("foo", "bar")
Stream<String> strings = options.flatMap(o -> o);
Here is a solution for the example of the initial question:
import javaslang.collection.Stream;
import javaslang.control.Option;
public class Test {
void run() {
// = Stream(Thing(1), Thing(2), Thing(3))
Stream<Thing> things = Stream.of(new Thing(1), new Thing(2), new Thing(3));
// = Some(Other(2))
Option<Other> others = things.flatMap(this::resolve).headOption();
}
Option<Other> resolve(Thing thing) {
Other other = (thing.i % 2 == 0) ? new Other(i + "") : null;
return Option.of(other);
}
}
class Thing {
final int i;
Thing(int i) { this.i = i; }
public String toString() { return "Thing(" + i + ")"; }
}
class Other {
final String s;
Other(String s) { this.s = s; }
public String toString() { return "Other(" + s + ")"; }
}
Disclaimer: I'm the creator of Javaslang.
Null is supported by the Stream provided My library abacus-common. Here is code:
Stream.of(things).map(e -> resolve(e).orNull()).skipNull().first();
What about that?
private static List<String> extractString(List<Optional<String>> list) {
List<String> result = new ArrayList<>();
list.forEach(element -> element.ifPresent(result::add));
return result;
}
https://stackoverflow.com/a/58281000/3477539
Most likely You are doing it wrong.
Java 8 Optional is not meant to be used in this manner. It is usually only reserved for terminal stream operations that may or may not return a value, like find for example.
In your case it might be better to first try to find a cheap way to filter out those items that are resolvable and then get the first item as an optional and resolve it as a last operation. Better yet - instead of filtering, find the first resolvable item and resolve it.
things.filter(Thing::isResolvable)
.findFirst()
.flatMap(this::resolve)
.get();
Rule of thumb is that you should strive to reduce number of items in the stream before you transform them to something else. YMMV of course.

Categories

Resources