This question already has answers here:
Java: avoid checking for null in nested classes (Deep Null checking)
(13 answers)
Closed 4 years ago.
I need a generic way for null check. I came up with a requirement.
This is my setter method for a class:
placeHolderValues.setCurrentAddressCountry(communicationSO.getApplicationDetailSO().getApplicantDetails().get(0).getAddressDetail().get(0).getCountry());
I want to set values in placeHolderValues.setCurrentAddressCountry() only when value is present. If any of the getApplicationDetailSO() or getApplicantDetails() or getAddressDetail() or getCountry() is NULL then I have to set NULL in placeHolderValues.setCurrentAddressCountry(). I have almost 30 such types of setter.
I need a common method to achieve the same.
A serious non-answer here: don't do it that way.
Using getA().getB().getC().getD()...getTheThingYouWant() is really bad practice.
It is a clear violation of the Law Of Demeter.
So besides the problem you run into (about checking null), such constructs are really actually evil. You see, the class using this code must know that an A has a B. And that B has a C. And so on. This directly couples this class with all classes A, B, C, ... and so on.
The real answer is to avoid such changing. If at all, you do getA().getMeWhatINeed().
The only other alternative: validate your input data completely (in an upfront step), before going down such call chains.
You could use Optional.ofNullable and repeatedly map the value into another, unless you encouter null on the way, and then get the final value orElse null.
var value = Optional.ofNullable(communicationSO)
.map(x -> x.getApplicationDetailSO())
.map(x -> x.getApplicantDetails())
.map(x -> x.get(0))
.map(x -> x.getAddressDetail())
.map(x -> x.get(0))
.map(x -> x.getCountry())
.orElse(null);
placeHolderValues.setCurrentAddressCountry(value);
This still is not very pretty, but at least you do not have to repeat the different method calls. Some of those lambdas (->) could probably also be replaced with proper Method references. (::) Still, it's probably better than just wrapping the line into a try block and catching the NullPointerExceptoin.
Related
I have gone through several null check related questions in Java and the best practices around it.
After long search , I can see Objects.nonNull () serves the purpose though it looks Orange instead of Apple.
Now i have a following check using Objects.nonNull() and short-circuiting logical AND.
if (Objects.nonNull (obj1) &&
Objects.nonNull (obj1.getObj2()) &&
Objects.nonNull (obj1.getObj2().getObj3 ())
{
obj1.getObj2().getObj3().doSomething();
}
I find it is more redundant and less readable when i clearly know my intention.
Is there any other approach to handle it in functional way to assert the non null state of the deeper object without facing Null pointer exception.
Using !=null is the normal way to do null-checks, but here's an alternative way that allows you to chain them using Optional.
Optional.ofNullable(obj1).map(class1::getObj2)
.map(class2::getObj3)
.ifPresent(class3::doSomething);
and you can use a lambda expression in place of any of the method references if the code you want to execute is not a simple function call.
Optional.ofNullable(obj1).map(x -> x.getObj2())
.map(x -> x.getObj3())
.ifPresent(x -> {
System.out.println("Now I can use my obj3 "+x);
});
So I'm new to Java8. I've read about streams, but most examples are very basic. I was wondering how it'd be done with nested objects. Here is an example from my code:
for (Gas gas : gases) {
resourceNodes.add(gas.getRefinery().unit());
}
It seems like I should be able to one-line this with a stream, but I can't quite figure it out. Could someone provide an answer with a stream. Is there a way to use :: syntax with nested methods too?
Edit:
To clarify the example, getRefinery() returns an object of type: UnitInPool, whose method unit() returns an object of type: Unit. resourceNodes is an ArrayList of Unit.
The :: syntax that you refer to is what's known as a method reference.
Assuming resourceNodes is unassigned (or empty, in which case you can remove any previous assignment) prior to the for-loop, then you'd want to first map each Gas to whatever type unit() returns, and then collect the Stream to a List:
resourceNodes = gases.stream()
.map(Gas::getRefinery)
.map(GasRefinery::unit)
.collect(Collectors.toList());
Otherwise, if your goal is to simply add to resourceNodes, then it would be very similar:
resourceNodes.addAll(gases.stream()
.map(Gas::getRefinery)
.map(GasRefinery::unit)
.collect(Collectors.toList()));
You need to provide more code for a reasonable answer, but I'm guessing you can get a stream of units, whetever these are (and whatever getRefinery returns) this way:
gases.stream().map(Gas::getRefinery).map(???::unit)
then you can for example collect the result with collect(Collectors.toList()) and just call resourceNodes.addAll with the collected result as parameter
resourceNodes = gases.stream().map(gas -> gas.getRefinery().unit()).collect(Collectors.toList());
If you want only method references, you can use this:
gases.stream().map(Gas::getRefinery).map(UnitInPool::unit).map(resourceNodes::add);
or
gases.stream().map(Gas::getRefinery).map(UnitInPool::unit).forEach(resourceNodes::add);
Otherwise, a lambda would likely be better since it's a lot shorter and more readable, and works, when you have methods that take multiple parameters or need to do multiple complex operations.
gases.stream().forEach(g -> resourceNodes.add(g.getRefinery().unit()));
This is basically the same as your previous code, but I would suggest the for-loop.
Welcome to the SO community. I hope the following helps.
List<Unit> resourceNodes = gases.stream() // open a stream
.map(gas -> gas.getRefinery()) // convert to UnitInPool
.filter(unitInPool -> Objects.nonNull(unitInPool)) // null check to avoid NPE
.map(unip -> unip.getUnit()) // convert to Unit
.collect(Collectors.toList()) // collect all the values in a List
A super simple question:
Here's my plain Java code using traditional ternary operator ?
public DateTime getCreatedAt() {
return !recordA.isPresent() ? recordB.get().getCreatedAt() : recordA.get().getCreatedAt();
}
My best bet is following:
public DateTime getCreatedAt() {
return recordA.map(
record -> record.getCreatedAt())
.orElse(recordB.get().getCreatedAt());
}
This could compile, but looks like it's not behaving correctly.
It always executes both branches, for e.g. when recordA isPresent(), it still executes recordB.get().getCreatedAt() which throws me
java.util.NoSuchElementException: No value present
Any help is appreciated!
Basically, I'd like to replace the traditional ternary operator with more advanced Optional/lamda features.
To avoid eagerly evaluating else-branches, use orElseGet, which takes an instance of the functional interface Supplier:
return recordA.map(
record -> record.getCreatedAt())
.orElseGet(() -> recordB.get().getCreatedAt());
You're looking for .orElseGet(() -> recordB.get().getCreatedAt()); and the reason to that can be found on this post --> Difference between Optional.orElse() and Optional.orElseGet()
Some people may find it a bit subjective but personally, I'd say by default, it makes more sense to use orElseGet() as opposed to orElse every time except in the case where the default object is already constructed as this will prevent many unexpected problems (given you didn't read the differences between orElse and orElseGet doc) as such of the one you're facing now.
read more from Java Optional – orElse() vs orElseGet()
My question about recordB being Optional got unanswered but if it is Optional then you cannot just safely call its get method, you need to check if it is empty or not. Here safe call to get record or null if both recordA and recordB are empty Otionals.
recordA
.map(Record::getCreatedAt)
.orElseGet( () -> recordB.map(Record::getCreatedAt).orElse(null) );
If you are using Java 9+, you may be able to use ifPresentOrElse() method as more completely explained in this Stackoverflow answer.
recordA.ifPresentOrElse(
value -> recordA.get().getCreatedAt(),
() -> recordB.get().getCreatedAt()
);
In Java 8,
I currently have a lambda that looks like this:
.createSomething((acceptableStates, someProxy) -> (userId) ->
acceptableStates.contains(someProxy.getSomeAttributeId(userId)))
However, we have changed someProxy.getSomeAttributeId to return an Optional<String> instead of a string.
What's the cleanest / most accepted way to essentially check for if acceptableStates contains the value of someProxy.getSomeAttributeId(userId) if the attribute returned isn't empty?
(Note: acceptableStates is still a list of strings, not of Optional<String>)
.... userId -> someProxy.getSomeAttributeId(userId)
.map(acceptableStates::contains)
.orElse(Boolean.FALSE);
Unfortunately, I see no very clean solution here. Refer to this question: Functional style of Java 8's Optional.ifPresent and if-not-Present?
Additionally, you even have to save the optional in a variable if the call to getSomeAttributeId does cost resources.
.createSomething((acceptableIds, someProxy) -> (userId) ->
{
Optional<String> attrId = someProxy.getSomeAttributeId(userId);
return attrId.isPresent() ? acceptableStates.contains(attrId.get()) : false;
})
I strongly recommend writing understandable and clear code like this snippet:
Optional<SomeAttributeId> optional = someProxy.getSomeAttributeId(userId);
return optional.isPresent() && acceptableStates.contains(optional.get());
If there should not be thrown an exception (1) when someProxy.getSomeAttributeId(userId) is an empty optional:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElseThrow(() -> new Exception()))
Or unless you have the default value (2) to fill up the result with:
acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElse(DEFAUT_VALUE))
My point:
Do not pursue Java 8 features which will mess everything up, especially in cases where a simple boolean expression could be used. I had experience refactoring some code toward plain Java statements because new people (1.1) came in a project could not get what the code does. With the time, even I (as a writer) barely can do so (1.2).
Also, with that "lambda chain" style, one slight change could cause rewriting a snippet/method entirely (2).
It is always fun to poke around n-nested lambdas, where n > 2 (3).
Anyway, if you don't share my point, #Eugene proposed a good way to go with.
return value.isPresent() && value.get().contains("some-text");
I have a question regarding the usage of the Function.identity() method.
Imagine the following code:
Arrays.asList("a", "b", "c")
.stream()
.map(Function.identity()) // <- This,
.map(str -> str) // <- is the same as this.
.collect(Collectors.toMap(
Function.identity(), // <-- And this,
str -> str)); // <-- is the same as this.
Is there any reason why you should use Function.identity() instead of str->str (or vice versa). I think that the second option is more readable (a matter of taste of course). But, is there any "real" reason why one should be preferred?
As of the current JRE implementation, Function.identity() will always return the same instance while each occurrence of identifier -> identifier will not only create its own instance but even have a distinct implementation class. For more details, see here.
The reason is that the compiler generates a synthetic method holding the trivial body of that lambda expression (in the case of x->x, equivalent to return identifier;) and tell the runtime to create an implementation of the functional interface calling this method. So the runtime sees only different target methods and the current implementation does not analyze the methods to find out whether certain methods are equivalent.
So using Function.identity() instead of x -> x might save some memory but that shouldn’t drive your decision if you really think that x -> x is more readable than Function.identity().
You may also consider that when compiling with debug information enabled, the synthetic method will have a line debug attribute pointing to the source code line(s) holding the lambda expression, therefore you have a chance of finding the source of a particular Function instance while debugging. In contrast, when encountering the instance returned by Function.identity() during debugging an operation, you won’t know who has called that method and passed the instance to the operation.
In your example there is no big difference between str -> str and Function.identity() since internally it is simply t->t.
But sometimes we can't use Function.identity because we can't use a Function. Take a look here:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
this will compile fine
int[] arrayOK = list.stream().mapToInt(i -> i).toArray();
but if you try to compile
int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();
you will get compilation error since mapToInt expects ToIntFunction, which is not related to Function. Also ToIntFunction doesn't have identity() method.
From the JDK source:
static <T> Function<T, T> identity() {
return t -> t;
}
So, no, as long as it is syntactically correct.