How to convert following method to java 8? - java

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

Related

Why doesn't Stream.mapToInt handle NullPointerExceptions?

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();

Better way to check for variable empty or null or parent is null

I have a condition in java as follows:
if(a == null || a.getRecords() == null || a.getRecords().isEmpty()) {
}
Is there a better way to write this condition using some google guava library or apache library?
Not sure if this solution is better, but you can use an Optional for that:
boolean result = !Optional.ofNullable(a)
.map(MyClass::getRecords)
.filter(List::isEmpty)
.isPresent();
if (result) {
// ...
}
A way of doing it is like so, using the null object pattern:
if (firstNonNull(firstNonNull(a, someNonNullInstance).getRecords(), emptyList()).isEmpty()) {
Where MoreObjects.firstNonNull and Collections.emptyList() are used.
This assumes that someNonNullInstance is an instance of the same type as a, with an empty records list (or whatever the type of getRecords() is).
I wouldn't recommend this, however. The original code is far more readable (I would go so far as to say that this is quite unreadable).
You could make it more readable by breaking up the expression:
TypeOfA anA = firstNonNull(a, someNonNullInstance);
List<Record> aList = firstNonNull(anA.getRecords(), emptyList());
if (aList.isEmpty()) {
// ...
}
but it still feels far worse that the original.
Seems you are working with collection here , If you use the Apache Commons Collections library in your project, you may use the CollectionUtils.isEmpty and MapUtils.isEmpty() methods which respectively check if a collection or a map is empty or null (i.e. they are "null-safe").
Also You can use org.apache.commons.lang.Validate's "notEmpty" method:
Validate.notEmpty(myCollection) -> Validate that the specified argument collection is neither null nor a size of zero (no elements); otherwise throwing an exception.
When you use spring then you can use
boolean isNullOrEmpty = org.springframework.util.ObjectUtils.isEmpty(obj);
where obj is any [map,collection,array,anything...]
But it seems To check an object is null is easy but to verify if it's empty is tricky as object can have many private or inherited variables and nested objects which should all be empty. For that All need to be verified or some isEmpty() method be in all objects which would verify the objects emptiness.
You can't do it directly, you should provide your own way to check this. Eg.
class MyClass {
Object attr1, attr2, attr3;
public boolean isValid() {
return attr1 != null && attr2 != null && attr3 != null;
}
}
Or make all fields final and initialize them in constructors so that you can be sure that everything is initialized.

How use findAny() and not return null

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.

Work with null value in Stream

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.

System.out.println() of Stream#reduce() unexpectedly prints "Optional[]" around result

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.

Categories