findFirst() gives you an Optional and you then have to decide what to do if it's not present. So findFirst().orElse(null) should give you the object or null if it's not present
You could just do a .get() on the Optional, but that could be regarded as poor practice since get() will throw an exception if Optional has no content. You should normally assert presence/absence of the Optional and decide what to do in each case (that's why it's there - so that you know something is truly optional and you have to determine what to do)
If you have an action you want to perform on object presence, and you don't want to do anything on absence, you can call .ifPresent() and provide a lambda as an argument. That will be called with the contained object, if present.
As of Java 9, a further solution would be to use Optional.ifPresentOrElse()
Answer from Brian Agnew on Stack OverflowfindFirst() gives you an Optional and you then have to decide what to do if it's not present. So findFirst().orElse(null) should give you the object or null if it's not present
You could just do a .get() on the Optional, but that could be regarded as poor practice since get() will throw an exception if Optional has no content. You should normally assert presence/absence of the Optional and decide what to do in each case (that's why it's there - so that you know something is truly optional and you have to determine what to do)
If you have an action you want to perform on object presence, and you don't want to do anything on absence, you can call .ifPresent() and provide a lambda as an argument. That will be called with the contained object, if present.
As of Java 9, a further solution would be to use Optional.ifPresentOrElse()
I think you may be looking for findFirst().or Else(null). findFirst() will return an Optional - empty in the case of an empty steam.
Unless I misunderstood your comment. Have you tried this, or did you try orElse(null) without findFirst()?
Creating an Optional out of the return value of a method seems a bit awkward. Rather let your getObjectOrNullIfNotAvailable() method return an Optional in the first place. Then use the map operator to convert it in to a string. Here's how it looks.
Optional<Object> oa = someOptionalReturningMethod();
String value = oa.map(Object::toString).orElse(null);
For some reason if you can't change the return value of the method to an Optional, just leave the imperative solution using the ternary operator. Nothing wrong with that.
String value = a==null ? null : a.toString();
Use:
String value = Optional.ofNullable(getObjectOrNullIfNotAvailable()).map(Object::toString).orElse(null);
Otherwise, you can check if an Object is null and return in that case a String with "null" inside with String.valueOf(Object obj) or Objects.toString(Object obj). Eg.
String value = Objects.toString(getObjectOrNullIfNotAvailable())
It’s not completely clear what you want the result to be, in particular not what you want in case one of the Optionals is empty. For this code snippet I have assumed that you want to leave those entries out.
Map<Object, Optional<Object>> originalMap = Map.of("Key 1", Optional.of(Integer.valueOf(2)),
Integer.valueOf(3), Optional.empty(),
"Key 4", Optional.of("Value 4"));
Map<Object, Object> targetMap = originalMap.entrySet()
.stream()
.filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElseThrow()));
System.out.println(targetMap);
Output is:
{Key 1=2, Key 4=Value 4}
I usually tell folks to avoid Optional.isPresent() as low-level. In this case I would use it. I don’t consider it bad code on my part, but rather a sign of bad API design as you already said.
In case you prefer not to use Optional.isPresent(), there is a way without it. The code gets less readable IMHO:
Map<Object, Object> targetMap = originalMap.entrySet()
.stream()
.flatMap(e -> e.getValue().stream().map(v -> Map.entry(e.getKey(), v)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
The result is the same as before.
If the output map had the same type you could use replaceAll overwrite the values in place.
Since the input and output maps have different types, you can use a stream to map the entries and create a new map:
Map<Object, Object> newMap = itemsMap
.entrySet()
.stream()
.collect(Collectors.toMap(
e -> e.getKey(),
e -> e.getValue().orElseThrow(
() -> new WhateverMyExceptionIs("Exception Message")
)
));