This code will give NullPointerException. Isn't the mapToInt (map) method supposed to handle NPE?
List<Integer> list = Arrays.asList(null, null);
OptionalDouble op = list.stream()
.mapToInt(val->val)
.average();
Why do you expect it to handle NullPointerException?
The lambda expression val->val is equivalent to:
new ToIntFunction<Integer> () {
int applyAsInt(Integer value) {
return value;
}
}
And when a method that has an int return type returns an Integer, auto-unboxing takes place. This means value.intValue() is called, and if value is null, NullPointerException is thrown.
mapToInt() simply calls the applyAsInt() method of the ToIntFunction instance passed to it for each element of the Stream.
It has no reason to check that an element is null and somehow handle it, since it has no way of knowing how you wish to deal with nulls. It's the job of the ToIntFunction instance to decide that, and your ToIntFunction doesn't handle nulls.
As Eran has already noted in his answer, the mapToInt is not supposed to handle NPE.
You have to deal with it instead, by providing your custom null-check logic. E.g.:
OptionalDouble op = list.stream()
.mapToInt(val -> val == null ? 0 : val)
.average();
I am fairly new to Java but had a similar problem. Reading over this and the documentation I came up with this -keep in mind, I'm using it for a slightly different reason but you will see how I was able to filter out the possibility of nulls to avoid the NPE.
positions.stream().filter(i -> i != null).mapToInt(i -> i).toArray();
Related
I have List object and I need to take the first element on the list if it is not null or empty.
I write below code using java and now I want to convert it to Java 8.
List<DD> container
A<DD,DI> a;
if(container!=null || !container.isEmpty()){
for(DD dd:container)
{
a = dd.getPrescription();
break;
}
}
I convert it like this.
DD detail = container.stream().findFirst().get();
I need to know this is correct?
There is a critical flaw in your current code, i.e.
if(container!=null || !container.isEmpty())
this can still throw a NullPointerException (when container == null), unless the conditional operator is changed to &&. Post which the implementation below would be what I would suggest following.
It's almost correct, in the sense that you need to handle some default value if the conditions are not met :
DD detail = container.stream().findFirst().orElse(null); // or some default value instead of 'null'
If the container itself could be null, use
DD detail = container != null ?
container.stream().findFirst().orElse(null) : null;
In the case when you need the prescription from this object, use map as :
container.stream().findFirst().map(DD::getPrescription).orElse(null)
// ^^
// return type of prescription then
With Java-9, this could have been much simpler as :
A<DD, DI> basePrescription = Stream.ofNullable(container) // Java-9 API
.flatMap(List::stream)
.findFirst()
.map(DD::getPrescription)
.orElse(null);
This is way easier:
A<DD,DI> a = container.get(0).getPrescription();
While this is a direct translation of your original code, you probably intended something like that:
A<DD,DI> a = container != null && !container.isEmpty()
? container.get(0).getPrescription()
: null;
As of JDK9, there is a new method T requireNonNullElse(T obj,
T defaultObj) which essentially returns the first argument if it is non-null and otherwise returns the non-null second argument.
We can, therefore, simplify your code to:
Objects.requireNonNullElse(container, Collections.emptyList())
.stream()
.findFirst()
.map(DD::getPrescription);
This returns an Optional<T> where T is whatever type getPrescription is. depending on the context and whether it's appropriate you might want to use .orElse(null); to get the value the optional contains or else a null value but there are also several other methods in the Optional<T> API which you might find more useful when extracting the value from the optional.
The findFirst() method finds the first element in a Stream. This method is used when you specifically want the first element from a sequence.
a) container.stream().findFirst().orElse(null);
b) container.stream().filter(Objects::nonNull).findFirst().orElse(null);
c)container.stream().filter(StringUtils::isNotBlank).findFirst();
or as lambdas:
d)container.stream().filter(s -> StringUtils.isNotBlank(s)).findFirst();
e)container.stream().filter(StringUtils::isNotBlank).findFirst()
For reference:- http://www.geekabyte.io/2015/01/using-optional-effectively-in-java-8.html
I would like to know how I can use findAny() in a data stream when it does not find any coincidence, it does not return null.
String CountryFinal= "Spain";
List<ParContriesTO> listContries = new ArrayList<SelectItem>();
listContries.add(new SelectItem(215, "Germany"));
Integer idCountry = (int) listContries.stream()
.filter(country -> country.getNoCountry().equals(CountryFinal))
.findAny().orElse(null).getCoCountry();
The Stream::findAny returns Optional and its method Optional::findAny, according to the documentation, there are 4 ways to return T:
Optional::get returns the T or throws NoSuchElementException
Optional::orElse returns T or a default value
Optional::orElseGet returns T or a value provided with Supplier
Optional::orElseThrow returns T or throws a custom exception
As far as I understand, you are looking for the second or third method which returns a defined value in case the origin is null. You can return a null-object using the Null-Object pattern which represents an object which is valid but does "nothing". Or else you can use null.
I suggest you receive a country before you let return null or anything alse and use getCoCountry() method on it (I suppose Country::getCoCountry returns either int or Integer) - otherwise, what have you done would return NullPointerException.
Try the following snippet:
Integer idCountry = listContries.stream() // Stream
.filter(c -> countryFinal.equals(c.getNoCountry())) // Get one equals to "Spain"
.findFirst() // Get Optional<Country>
.map(Country::getCoCountry) // If exists, get its code
.orElse(0); // Or else return an invalid code
Note there is no need to both filter by the country name and then check the equality since you expect there is only one "Spain".
The approach to invoke getCoCountry as last is generally bad.
What you could do is:
listContries.stream()
.filter(country -> country.getNoCountry()
.equals(CountryFinal))
.findAny().map(Country::getCoCountry).orElse(WHATEVER_YOU_WANT);
To clarify: findAny returns Optional that may contain an instance of country. You can safely invoke getCoCountry in map. This is the importance of Optional type. At this step, you're still safe since you still have an Optional that MAY contain an Integer result. In the end, you can use orElse to decide what you want to have if instance is null.
I have some function with lambda which is returning some object or null
public Function<SomeObject1, SomeObject2> lambdaFunc = obj1 -> {
// here I do some logic, convert obj1 to obj2 and on the end return obj2 or null
};
I am using that function in my stream like that:
someObj0.setObjects2(entity.getObjects1().stream().map(lambdaFunc).collect(Collectors.toSet()));
Here when lambdaFunc return null I got exception, I think it is due collect function. Is some pretty solution to do that? I will be ok if that stream return also null when lambdaFunc return null, and don't continue.
EDIT 1:
Ok I tried filter(Objects::nonNull) function but I find out problem is with entity.getObjects1() so I need prevent call stream function if it return null, any ideas?
You can sinply add filtering for nonNull values:
someObj0.setObjects2(
Optional.ofNullable(entity.getObjects1())
.orElse(Coollections.emptyList()) // return original Object or singleton empty from Collections
.stream()
.map(lambdaFunc)
.filter(Objects::nonNull) // add checking here
.collect(Collectors.toSet()));
Here you have two choices:
First would be to wrap getObjects1() in a Optional
Second would be more clean - never return null, initialize your object with empty collection at start. Methods that return collections should never return null, but an emptyCollection from Collections util class. So that you would not have to worry about the nulls.
so
class SomeObj0 {
private List<SomeObject1> col =Collections.emptyList();
// getters/setters
}
I assume your collections is a list, but you can prevent it with a Optional:)
I think this is the case where you should use Optional instead of null.
You don't have much details about what entity.getObjects1() is doing, but one thing is for sure, if you avoid returning null all along it will save you a NullPointerException further on.
You can try something like this which is clearer as to the intent you are doing:
Optional.ofNullable(entity.getObjects1())
.map(objects -> objects.stream()
.filter(Objects::nonNull)
.map(lambdaFunc)
.collect(Collectors.toSet()))
.ifPresent(someObj0::setObjects2)
If you change entity.getObjects1() to return Optional you avoid the first call to ofNullable().
I would also encapsulate the objects.stream() part to another method that takes the collection and lambda function and returns another collection, to make the code a bit clearer.
how to rewrite this function to be more Java 8 with Optionals? Or should I just leave it as it is?
public void setMemory(ArrayList<Integer> memory) {
if (memory == null)
throw new IllegalArgumentException("ERROR: memory object can't be null.");
if (memory.contains(null))
throw new IllegalArgumentException("ERROR: memory object can't contain null value.");
this.memory = memory;
}
You've got a pattern condition -> throw an exception which can be moved to a method:
private void checkOrElseThrow(boolean condition, Supplier<? extends RuntimeException> exceptionSupplier) {
if (condition) {
throw exceptionSupplier.get();
}
}
public void setMemory(List<Integer> memory) {
checkOrElseThrow(memory == null, () -> new IllegalArgumentException("message #1"));
checkOrElseThrow(memory.contains(null), () -> new IllegalArgumentException("message #2"));
this.memory = memory;
}
If the type of the exception is not going to be changed, it's reasonable to pass only the message of the exception (thank #tobias_k for pointing it out):
private void checkOrElseThrow(boolean condition, String exceptionMessage) {
if (condition) {
throw new IllegalArgumentException(exceptionMessage);
}
}
public void setMemory(List<Integer> memory) {
checkOrElseThrow(memory == null, "message #1");
checkOrElseThrow(memory.contains(null), "message #2");
this.memory = memory;
}
If you want to stick to IllegalArgumentException and you have guava on the class path, you could use this:
Preconditions.checkArgument(memory != null,
"ERROR: memory object can't be null.");
Preconditions.checkArgument(!memory.contains(null),
"ERROR: memory object can't contain null value.");
You can't really use Optional here since you want different error messages for different conditions.
If you are OK having a single error message on the other hand, you could do:
this.memory = Optional.ofNullable(memory)
.filter(x -> !x.contains(null))
.orElseThrow(() -> new IllegalArgumentException(
"memory object is null or contains null values"));
For the first case I would use:
Objects.requireNonNull().
I don't think Optional is a way to go here as null is an illegal value.
I usually avoid Optional for such cases as it tends to obscure what's going on.
But first I'd like to mention that the original code lets the caller retain a reference to what is now an internal field memory of the containing class. Maybe you trust your callers not to be malicious, but the caller might accidentally reuse the list passed as an argument. If it does, despite the meticulous argument checking, the memory list might end up containing nulls after all. Or, it could change unexpectedly, leading to other malfunctions.
The solution is to make a defensive copy of the argument list. The straightforward way to do this is as follows:
public void setMemory(ArrayList<Integer> memory) {
if (memory == null)
throw new IllegalArgumentException("memory is null");
List<Integer> temp = new ArrayList<>(memory);
if (temp.contains(null))
throw new IllegalArgumentException("memory contains null");
this.memory = temp;
}
Note that the copy is made and stored in a local variable temp prior to being checked. Obviously, you don't want to store into the field before the list is checked for containing nulls. But the check for containing nulls should be done on the copy, not on the argument list, otherwise, the caller could modify the list after the check but before the copy. (Yes, this is being paranoid.)
If you don't care about the exact exception message, this could be shortened as follows:
public void setMemory(ArrayList<Integer> memory) {
List<Integer> temp;
if (memory == null || ((temp = new ArrayList<>(memory)).contains(null)))
throw new IllegalArgumentException("memory is or contains null");
this.memory = temp;
}
Now this could be rewritten to use Optional:
public void setMemory(ArrayList<Integer> memory) {
this.memory = Optional.ofNullable(memory)
.map(ArrayList::new)
.filter(list -> ! list.contains(null))
.orElseThrow(() -> new IllegalArgumentException("memory is or contains null"));
}
Compared to the usual abuses :-) of Optional I see frequently, this one isn't too bad. The chaining here serves to avoid creation of a local variable, which is a bit of a win. The logic is fairly straightforward, especially if one has Optional on the forebrain. However, I'd be somewhat concerned about revisiting this code in, say, a month. You'd probably have to squint at it a while before convincing yourself it does what you intended it to do.
Finally, a couple general style comments.
The usual preference (at least in the JDK) is to use NullPointerException for these cases. I've stuck with IllegalArgumentException for these examples because that's what the OP is using.
I'd recommend using List<Integer> instead of ArrayList<Integer> for the argument type and possibly the field type. This will enable the use of unmodifiable lists in situations where it's appropriate (e.g., using JDK 9's List.of).
First, it may be a good idea to use the more general list type as input parameter, so change your implementation to:
public void setMemory(List<Integer> memory) {
//stuff
}
and then as others mentioned, checking for null values for every "set" operation is a bit of an overkill.
If this "memory list" comes from some of your code and you can use guava, then maybe use guavas immutable list. This list throws an exception when someone tries to add "null" to your list.
ImmutableList.of( //your Integers)
If you cannot use guava but stillt want to use that approach you could always write your own list implementation that does this null checking for you.
And last, if all of this is not possible for you, just leave your code as is. It is very easy to read and everyone knows what you're doing. Using Optionals can be quite confusing as you can see in other answers here.
One liner with Optionals:
public void setMemory(ArrayList<Integer> memory) {
this.memory = Optional.ofNullable(memory).map((a) -> Optional.ofNullable(a.contains(null) ? null : a).orElseThrow(() -> new IllegalArgumentException("ERROR: memory object can't contain null value."))).orElseThrow(() -> new IllegalArgumentException("ERROR: memory object can't be null."));
}
Sorry for adding yet another answer, but based on reading comments to the question, there might be even better way to change signature of the method: replace ArrayList<Integer> with IntStream:
public void setMemory(#NonNull IntStream input) {
Objects.requireNonNull(input);
this.memory = ...; // collect the stream into the storage
}
Primitive streams do not incur cost of (un)boxing.
This way you don't have to worry about the caller changing List contents under your feet, and will be able to chose the suitable storage for integers as explained in my other answer (or even resolve the stream contents lazily!).
Do not use Optionals, they won't benefit you here.
Instead use a more suitable type in place of ArrayList. Storing Integers in collection incurs (un)boxing costs and does not make sense when nulls are not allowed.
Few possible collection libraries, that may suite your needs better:
HPPC collections (my favorite, but API is incompatible with Java Collection framework)
Koloboke
Fastutil
All of those libraries provide specialized implementations of Lists, Maps and other containers for primitives. Those implementations are generally significantly faster than anything that involves ArrayList<Integer> (unless all integers in your ArrayList are small enough to fit into global Integer instance cache).
As a nice side-effect, using specialized Lists of primitive integers won't allow caller to store nulls by default.
My solution may be used only if you need two different exceptions and more functional style. But it looks complicated and even longer.
.map(e -> false) maps element of list (integer in this case) to boolean which is required for filter().
this.memory = Optional.ofNullable(memory)
.orElseThrow(() -> new IllegalArgumentException("ERROR: memory object can't be null."))
.stream()
.filter(element ->
Optional.ofNullable(element)
.map(e -> true)
.orElseThrow(
() -> new IllegalArgumentException("ERROR: memory object can't contain null value.")))
.collect(Collectors.toList());
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?
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.
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 return true and get() 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.
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
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.
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.