I'm trying to compare the minimal values of two arrays.
I'm getting the following compilation error:
Operator '>' cannot be applied to 'java.util.OptionalInt', 'java.util.OptionalInt'
What am I doing wrong?
My code:
public static void main(String[] args) {
int [] ints = {12,6,8,242};
int [] ints1 = {5,1,5432,5,76,146,8};
if(Arrays.stream(ints).min()>Arrays.stream(ints1).min()){
System.out.println(Arrays.stream(ints1).min());
}
}
CodePudding user response:
The issue here is that min
returns an OptionalInt
. This is beacuse calling min
on an empty stream would be nonsensical (what int would it return?).
If you are certain your streams will never be empty, you can call get
on the result of min
to unwrap the optional and throw if it is empty. I would recommend specifying some behaviour in the case of an empty stream though. There are multiple methods on Optional to make this easy to do. (OptionalInt
has the same API as Optional<T>
but wraps a primitive int
)
CodePudding user response:
min()
retrieves OptionalInt
. So to get and primitive int
you have to call getAsInt()
:
int[] one = { 12, 6, 8, 242 };
int[] two = { 5, 1, 5432, 5, 76, 146, 8 };
if (Arrays.stream(one).min().getAsInt() > Arrays.stream(two).min().getAsInt())
System.out.println(Arrays.stream(two).min().getAsInt());
Another option is to use Apache
:
import org.apache.commons.lang.math.NumberUtils;
int[] one = { 12, 6, 8, 242 };
int[] two = { 5, 1, 5432, 5, 76, 146, 8 };
if (NumberUtils.min(one) > NumberUtils.min(two))
System.out.println(NumberUtils.min(two));
CodePudding user response:
Obviously, you can't compare two Optional
objects using relational operators <
, or >
which are meant to be used only with primitive numbers.
In a nutshell, Optional
- is a container of data, which might contain a resulting value or might not. Regardless of whether result is present, you can safely interact with this container, that's the core idea behind the Optional.
Optional API contain lots of methods for dialing with it. You can perform various manipulations with the optional (like transforming or filtering its value) without unpacking it. And when obtain the contained value get()
(or getAsInt()
in the case of OptionalInt
) which is mentioned in another answer is the last option you should think of.
Here's a quote from the answer by Brian Goetz, Java Language Architect.
NEVER call
Optional.get
unless you can prove it will never be null; instead use one of the safe methods likeorElse
orifPresent
. In retrospect, we should have called get something likegetOrElseThrowNoSuchElementException
or something that made it far clearer that this was a highly dangerous method that undermined the whole purpose of Optional in the first place. Lesson learned.UPDATE: Java 10 has
Optional.orElseThrow()
, which is semantically equivalent toget()
, but whose name is more appropriate.
To perform an action on a result contained withing the Optional, API offers a method Optional.ifPresent()
, which expects a Consumer representing the action, which would be fired if the value is exists.
You can perform comparison of two values contained within Optionals, and print the first of them only both are present, and the first is greater than the second using the following approach:
int[] ints = {12, 6, 8, 242};
int[] ints1 = {5, 1, 5432, 5, 76, 146, 8};
getMin(ints).ifPresent(min1 -> getMin(ints1).ifPresent(min2 -> {
if (min1 > min2) System.out.println(min1);
}));
To avoid repeating the same stream statement generating the optional result we can introduce a method:
public static OptionalInt getMin(int[] arr) {
return Arrays.stream(arr).min();
}