问题
I started to learn Lambda expressions of Java 8, and wrote below program to get sum of all numbers in the list:
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String[] args) {
List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(number.stream().reduce((c,e) -> {
return c + e;
}));
}
}
I was expecting the output to be:
15
but I got:
Optional[15]
Java version: 1.8.0_45
- Please explain what does Optional[] means in the output?
- Does it has any significance in Java 8?
回答1:
From the Java Docs for Stream#reduce(), we see that the reduce operation returns an Optional<T>
. An Optional simply wraps a value if there is a value present, otherwise is "empty".
Important operations on Optional
include Optional#isPresent, which lets you know if there is something in the Optional or not, Optional#get, which returns the T
wrapped in the Optional and throws an exception if called on Empty, and Optional#orElse which returns the T
wrapped in the Optional if present, or the returns the default value provided if called on Empty.
For your case, the rationale behind reduce()
returning an Optional<Integer>
is that the list you're trying to reduce may be empty. In that case, the Integer
that should be returned is not well defined. For your specific intention 0
would be acceptable (As the sum of the elements in an empty list is 0
), thus you can get the sum as follows:
int sum = number.stream().reduce((c,e) -> c + e).orElse(0);
That way, even if the list is empty, you will still get a result that defines the sum of the list.
回答2:
reduce(BinaryOperator<T> accumulator):
Returns an
Optional
describing the result of the reduction
Optional:
A container object which may or may not contain a non-null value. If a value is present,
isPresent()
will returntrue
andget()
will return the value.
The reason reduce()
returns an Optional
, is because the stream might be empty, in which case there would be nothing to reduce, aka no value, and an Optional.empty() would be returned.
回答3:
In order to avoid Optional in the return you can call to this other method https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-T-java.util.function.BinaryOperator- Just add the identity: "0" before adding the lambda expression. Note that now there is only a 0 as a fist parameter to the reduce call.
System.out.println(number.stream().reduce(0,(c,e) -> {
return c + e;
}));
returns just
15
回答4:
Got it, thanks @Mshnik and @TimoSta. According to source code of Optional<> which overrides toString
method
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
Above code adds that Optional[]
in my output stream.
回答5:
From java.lang.Object.Optional:
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
Optional
offers two different primary methods for retrieving its value.
public T get() simply returns the value enclosed in the Optional
, but throws a NoSuchElementException
if the Optional
does not wrap a value.
orElse(T other) returns the value enclosed in the Optional or other
if the Optional
does not enclose a value.
EDIT (thanks @Brian Goetz):
Generally, orElse()
is a better choice since get()
returns a NoSuchElementException
if the Optional
contains a null value. True, in this case you will always recieve a value in Optional
but it's still good practice to primarily use orElse()
.
So, in your case, you would change
System.out.println(number.stream().reduce((c,e) -> {
return c + e;
}));
to:
System.out.println(number.stream().reduce((c,e) -> {
return c + e;
}).orElse(0));
which will return the desired value of 15
.
And as @Brian Goetz said in the comments, if you really wanted to make it succinct you could use Integer::sum
and a method reference:
System.out.println(number.stream.reduce(Integer::sum).orElse(0))
which is equivalent to using the longer lambda.
来源:https://stackoverflow.com/questions/35384145/system-out-println-of-streamreduce-unexpectedly-prints-optional-around