I want to validate below condition but something is going wrong with my if condition and returning invalid results. My validations are:
Either productId
or productAltID
can have value or both can be null
If both productId
and productAltID
are null, then productSellDate
and productReturnDate
must have value.
If productSellDate
and productReturnDate
are null
, then productId
or productAltID
should have value.
Please find my code below, I'm getting incorrect result not sure what I'm messing up here:
public class validate {
public static void main(String[] args) {
String productId = null;
String productAltID = "adfafadsf";
Date productSellDate = null;
Date productReturnDate = new Date();
if (productId != null || productAltID != null || productSellDate !=null && productReturnDate != null) {
System.out.println("validation success");
} else {
System.out.println("validation failed");
}
}
}
// Valid Scenarios
Combination 1: Valid Scenario
String productId = null;
String productAltID = null;
Date productSellDate = new Date();
Date productReturnDate = new Date();
Combination 2: Valid Scenario
String productId = null;
String productAltID = "3432fefsf";
Date productSellDate = new Date();
Date productReturnDate = new Date();
Combination 3: Valid Scenario
String productId = "sdf3234234324";
String productAltID = "3432fefsf";
Date productSellDate = null;
Date productReturnDate = null;
Combination 4: Valid Scenario
String productId = null;
String productAltID = "3432fefsf";
Date productSellDate = null;
Date productReturnDate = null;
The compare() method in StringUtils class is a null-safe version of the compareTo() method of String class and handles null values by considering a null value less than a non-null value. Two null values are considered equal.
out. println("(Object)string == number: " + ((Object)string == number)); To conclude this post and answer the titular question Does null equal null in Java? the answer is a simple yes.
The || operator can only be used, in Java, where a boolean (true or false) expression is expected, such as in an if statement like the above. So pretty much in an if or a conditional operator (that ?...: thing, sometimes called the ternary operator).
As noted, the operator &&
binds tighter than ||
so the logic wasn't doing what you wished it was. See Operators page of the Oracle tutorial.
A little Literate Programming goes a long way to avoiding this sort of thing.
boolean hasAnId = productId != null || productAltID != null;
boolean hasDates = productSellDate != null && productReturnDate != null;
if ( hasAnId || hasDates ) ...
The Answer by drekbour is correct, operator precedence rules and the lack of parentheses mean your ||
and &&
operators execute in an order different than you intend.
Here is an alternative approach using Objects.nonNull
and streams to execute the logic you want, in a readable format.
Stream
.of( productId , productAltID )
.anyMatch( Objects :: nonNull ) // One or more ID fields have a value.
|| // … or …
Stream
.of( productSellDate , productReturnDate )
.allMatch( Objects :: nonNull ) // All dates have a value.
Objects.nonNull
Modifying the code by drekbour, I would suggest using Objects.nonNull
& Objects.isNull
for easier reading.
Also, I would use more descriptive variable naming.
boolean atLeastOneIdHasValue = Objects.nonNull( productId ) || Objects.nonNull( productAltID ) ; // One or both ID fields have a value.
boolean bothDatesHaveValue = Objects.nonNull( productSellDate ) && Objects.nonNull( productReturnDate ) ; // Both dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;
Another approach uses streams.
Make a stream of your variables:
Stream.of( productId , productAltID )
Then tally if any or all match our criterion.
Stream#anyMatch
to see whether any elements of this stream match the provided predicate.Stream#allMatch
to see whether all elements of this stream match the provided predicate.In our case, the predicate is simply a call to Objects.nonNull
.
boolean atLeastOneIdHasValue = Stream.of( productId , productAltID ).anyMatch( x -> Objects.nonNull( x ) ) ; // One or more ID fields have a value.
boolean bothDatesHaveValue = Stream.of( productSellDate , productReturnDate ).allMatch( x -> Objects.nonNull( x ) ) ; // All dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;
We can shorten that code by using a method reference as our predicate: Objects :: nonNull
.
boolean atLeastOneIdHasValue = Stream.of( productId , productAltID ).anyMatch( Objects :: nonNull ) ; // One or more ID fields have a value.
boolean bothDatesHaveValue = Stream.of( productSellDate , productReturnDate ).allMatch( Objects :: nonNull ) ; // All dates have a value.
boolean valid = ( atLeastOneIdHasValue || bothDatesHaveValue ) ;
See this code run live at IdeOne.com.
Date
classBy the way, never use Date
class, nor Calendar
, SimpleDateFormat
, Timestamp
, etc. Those are now legacy, part of the terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
LocalDate
.Instant
.ZonedDateTime
.Let's put it like this:
public static boolean isValid(
String productId, String productAltId, Date sellDate, Date returnDate
) {
if (null == productId && null == productAltId) {
return null != sellDate && null != returnDate; // dates MUST have value
}
// here productId or productAltId have value, no need to check dates
return true;
}
Tests:
System.out.println(isValid(null, null, new Date(), new Date())); // true
System.out.println(isValid(null, "ab", new Date(), new Date())); // true
System.out.println(isValid("cd", "ab", null, null)); // true
System.out.println(isValid("cd", null, null, null)); // true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With