Reducing conditions within a if statement - java

I have a code snippet as below. Here there is a nested if else loop as well as multiple conditions [all different parameters]. What is the best way to optimize this.
if(request!=null && !StringUtils.isBlank(request)) {
if(request.getFirstName()!=null && !StringUtils.isBlank(request.getFirstName())
&& request.getLastName()!=null && !StringUtils.isBlank(request.getLastName())
&& request.getAge()!=null && !StringUtils.isBlank(request.getAge())
&& request.getAddress()!=null && !StringUtils.isBlank(request.getAddress())
&& request.getPhoneNumber()!=null && !StringUtils.isBlank(request.getPhoneNumber())) {
return true;
}else {
return false;
}
}else {
return false;
}
I had thought of using switch case and for loop as well but all the conditions are based on different variables, I didn't see it as compatible.

StringUtils from commons-lang already has a method which accepts an array of Strings. It will check for null or empty or blank strings. So all your checks boil down to:
return !(request == null || StringUtils.isAnyBlank(
request.getFirstName, request.getLastName,
request.getAge, request.getPhoneNumber));

You can try StringUtils.isAnyBlank(). Please refer attached link.
isAnyBlank : https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isAnyBlank-java.lang.CharSequence

If you don't use commons-lang dependency you can simply use Stream API (Java 8+)
Boolean allNonBlank = Stream.of(
request.getFirstName(),
request.getLastName(),
request.getAge(),
request.getPhoneNumber())
.allMatch(it -> it != null && !String.isBlank(it));

You have a few syntax errors
You are passing request to StringUtils but it doesn't appear to implement CharSequence
You are using !! instead of !
You invocation of the get methods does not include the () to mark it as methods.
Although not an error, you do not need nested if-statements here. Using unnecessary if-else-blocks can make it harder to decipher what the code is doing. It can, however, allow for comments to describe why certain conditions are being checked or whatever. None of that seems relevant here. In fact, you can pass the result of the boolean operation without any if-statement. Using if-statements that return true or false looks like this.
if (<condition-is-true?>) return true
else return false;
Which can be simplified to...
return <condition-is-true?>;
Further, assuming you are using using Apache StringUtils, you do not need to check for null first - the isEmpty(CharSequence) method does that. Additionally, StringUtils includes the isAnyEmpty(CharSequence...) method so you can pass all of the Strings at once.
return request != null && !StringUtils.isAnyEmpty(
request.getFirstName(),
request.getLastName(),
request.getAge(),
request.getAddress(),
request.getPhoneNumber());

Related

Why does Intellij idea warn about nullpointer in that if condition?

Here is my code
if (!multipartFile.isEmpty() && multipartFile.getOriginalFilename() != null && !multipartFile.getOriginalFilename().isBlank()) {
String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}
Here is how I see that code
As you can see, the last part of IF condition is underlined as Idea thinks that getOriginalFilename can return null, but I've checked this with that line of a code
multipartFile.getOriginalFilename() != null. What am I doing wrong?
Idea thinks that getOriginalFilename can return null
Because it can.
but I've checked this with that line of a code multipartFile.getOriginalFilename() != null
You checked that the previous invocation did not return null. The next one still can.
What am I doing wrong?
Calling a method twice in rapid succession, instead of storing its result in a variable and using that one for the check and the further processing. In fact you then call it for a 3rd time.
(this was just a copy of my comment from above)
While there may be ways to simplify the condition as the other answer shows, as you also need the result of getOriginalFilename() inside the if, I would assume the IDE will complain about that one next, and at the end you will probably have to bite the bullet and have a variable for it:
String originalFilename = multipartFile.getOriginalFilename();
if (!multipartFile.isEmpty() && originalFilename != null && !originalFilename.isBlank()) {
String fileName = StringUtils.cleanPath(originalFilename);
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}
You could simplify that expression by using the StringUtils:
!StringUtils.isNullOrEmpty(multipartFile.getOriginalFilename())
There are other functions in that utility class that might be helpful depending on what you're trying to do.
IntelliJ isn't always right but is always good to look a bit more in detail to our code to see what can be improved/simplified for better debugging/readability.

Elegant solution for two Optionals, if one is present the other must not be empty

I look for a more elegant solution of this code:
var first = Optional.ofNullable(a);
var second = Optional.ofNullable(b);
if ((unit.isPresent() && value.isEmpty()) || (value.isPresent() &&
unit.isEmpty())) {
throw new ExpWhatever();
}
Conditions are:
if both optionals are null -> ok, no error/excpt.
if one of the given optionals is present the other must not be empty too (otherwise: excpt.)
Thanks for any ideas or help.
It sounds like it's an error for isPresent() to be true for exactly one of them - so XOR works well:
if (unit.isPresent() ^ value.isPresent()) {
// Throw an exception
}
If you want both optionals to be either present or empty (i.e. they have the same "emptiness" state), you could use this:
if (unit.isPresent() != value.isPresent()) {
//throw an exception
}

Is there an easy way to compare scheme:host:port part of URI's to see if they are equal?

If I have two URI's, is there an easier way to compare the base URI rather than having to do the following?
URI firstURI = new URI("https://localhost:8000");
URI secondURI = new URI("https://localhost:8000/testing");
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort())
{
//error
}
You could have used the URI.equals() method but it doesn't suit at all to your requirement as it relies on really different rules.
Here is an extract of :
For two URIs to be considered equal requires that either both are
opaque or both are hierarchica*. Their schemes must either both be
undefined or else be equal without regard to case. Their fragments
must either both be undefined or else be equal.
So you don't have really the choice : create a utility method and use it such as :
public boolean isURIMatch(URI firstURI, URI secondURI){
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort()) {
return false;
}
return true;
}
You can shorten it slightly by comparing the values of getAuthority(), which returns everything between the scheme and path:
if (!firstURI.getAuthority().equals(secondURI.getAuthority()) ||
!firstURI.getScheme().equals(secondURI.getScheme()))
Be aware that the authority also includes the user info (username and password), but few URLs use that anymore, so unless you’re expecting URIs with login information in them, the above comparison should be safe.

IntelliJ IDEA Reporting Contract Violation Warning

Here is the Java code:
public static boolean anyEqual(Object needle, Object... haystack) {
if(needle == null || haystack == null) {
return false;
}
if(haystack.length == 0) {
return false;
}
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true; // warning from IntelliJ here, 'contract clause !null, null -> false is violated'
}
}
return false;
}
Does anyone have any idea why this is being shown? contract clause !null, null -> false is violated? Thanks!
IntelliJ 14.0.2 build: 139.659
Screenshot:
IntelliJ is inferring the formal contract of your method to be this:
null, _ -> false; !null, null -> false
What this actually means:
The first contract specifies that, so long as the first parameter is null, it will return false. This is observed by your first if statement:
if(needle == null || haystack == null) {
return false;
}
The second contract specifies that, if the second parameter is null, then it will return false. This is also specified by the same if statement above.
My gut is telling me that IntelliJ is having some trouble discerning what the loop's formal contract is in addition to all of the above, although it'd be as simple as another condition in the contract expression.
for(Object match : haystack) {
if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
return true;
}
}
Let's briefly go through this.
The enhanced-for statement won't fire if haystack is of length 0, so that's something to take into consideration.
The elements inside of the array could be null, and I'm not entirely sure that IntelliJ's static analysis covers that piece yet.
We've established already that needle must be non-null, so there's nothing violating the contract at that line.
If we have a scenario in which match != null && needle.getClass() == match.getClass() && needle.equals(match) is true, we return true. Otherwise, we return false.
There's nothing that I can see in the formal documentation that gives us the expression we require to say, "hey - we're checking elements of an array!"; it may be the case that the analysis is tripping up on the fact that we're returning true in spite of what we stated above (since haystack is non-null).
Allow me to stress this point:
haystack has to be non-null in order for you to enter into the enhanced-for. Your code will not work otherwise.
All in all, I wouldn't worry about it. Better yet, file a bug against it so that this sort of thing could be fixed or expanded upon.
This looks like an IntelliJ bug to me, since by removing the static keyword from the method the warning disappears.
Something must be confusing the static analysis here. One can always submit this to youtrack so jetbrains devs can look at it.
Someone already reported this issue Here
(tested on v14.0.3)
This message is being shown because IntelliJ checks for method contract violations. It's a relatively new feature, read more at https://www.jetbrains.com/idea/features/annotation_java.html

Format a Date, allowing null

I'm trying to print a Date, just the way DateFormat.getDateTimeInstance() does it.
format throws a NullPointerException when passing null, so I've been wondering if there is a different approach that would return null (or "null") instead?
Something I'd call instead of
Date d = null;
System.out.println(d==null ? null : DateFormat.getDateTimeInstance().format(d));
You could just wrap the call inside a utility method :
public class DateUtils {
public static String formatDateTime(Date dateOrNull) {
return (dateOrNull == null ? null : DateFormat.getDateTimeInstance().format(dateOrNull));
}
}
private constructor and javadoc omitted for brevity.
What's the problem with your existing code?
null is kind of a special case, and you've decided that you want one particular behaviour in this case (returning "null") instead of another particular behaviour (throwing an NPE). It's arguably cleaner to express this via switching at the top level rather than burying this logic within the formatting method.
It might be a little cleaner to use a full if-else rather than a tertiary operator, though, to make it clearer that there are two distinct branches (normal, and special-cased null):
if (d == null) {
return "null"; // or whatever special case
}
else {
return DateFormat.getDateTimeInstance().format(d);
}
The return value in the null case should be made clear in your method's javadocs, too.

Categories