How to refactor this Java snippet - java

For some reason, I can't help but see redundancy in this chunk of code. Can anybody help me refactor it be more readable and concise?
if (cachedParty == null || !cachedParty.equals(partyDto)) {
if (cachedParty == null
&& partyDto.getSellerStatusCode()
.equalsIgnoreCase(SellerStatusEnum.ACTIVE.getCode()))
{
pricingControlList.add(convertPartyDtoToPricingControl(partyDto));
} else if (!cachedParty.equals(partyDto)
&& cachedParty.getSellerStatusCode()
.equalsIgnoreCase(SellerStatusEnum.ACTIVE.getCode())
&& !partyDto.getSellerStatusCode()
.equalsIgnoreCase(SellerStatusEnum.ACTIVE.getCode())
) {
pricingControlList.add(convertPartyDtoToPricingControl(partyDto));
}
partyCache.put(partyDto.getSellerServicerNumber(), partyDto);
partiesToSaveOrUpdate.add(partyDto);
}

The comparison to SellerStatusEnum.ACTIVE may be implemented as a function accepting a Supplier<String>
Top level comparison may be simplified to remove cachedParty == null - it is assumed from the code that partyDto is not null and therefore it is enough to check !partyDto.equals(cachedParty)
An example implementation:
Function<Supplier<String>, Boolean> active = x -> SellerStatusEnum.ACTIVE.getCode().equalsIgnoreCase(x.get());
if (!partyDto.equals(cachedParty)) {
boolean partyActive = active.apply(partyDto::getSellerStatusCode);
if (null == cachedParty && partyActive
|| null != cachedParty && !partyActive && active.apply(cachedParty::getSellerStatusCode)
) {
pricingControlList.add(convertPartyDtoToPricingControl(partyDto));
}
partyCache.put(partyDto.getSellerServicerNumber(), partyDto);
partiesToSaveOrUpdate.add(partyDto);
}

I would suggest making helper method isActive(party) which returns partyDto.getSellerStatusCode().equalsIgnoreCase(SellerStatusEnum.ACTIVE.getCode(). Additionaly, there is a possible NPE when cachedParty == null because !cachedParty.equals(partyDto) is calling equals for null. So, considering that partyDto is never null, this can be reduced to !partyDto.equals(cachedParty).
Also, you're calling same method in if(x) else if (y) statement, so it can be reduced to one if statement with x or y check. So, let's rewrite your statement:
if (A or B) {
if ((A and C) or (B and D and !C)) { F() }
G()
}
As we decided in the first paragraph, A or B = B. So expression now looks like
if (B) {
if ((A and C) or (B and D and !C)) { F() }
G()
}
// and because inside first if statement B = true, we can remove B from nested if:
if (B) {
if ((A and C) or (D and !C)) { F() }
G()
}
So, by doing these optimisations we can get:
if (!partyDto.equals(cachedParty)) {
if (cachedParty == null && isActive(partyDto) || (isActive(cachedParty) && !isActive(partyDto)) {
pricingControlList.add(convertPartyDtoToPricingControl(partyDto));
}
partyCache.put(partyDto.getSellerServicerNumber(), partyDto);
partiesToSaveOrUpdate.add(partyDto);
}
I've noticed that there is no cachedParty != null check in your nested if, so final result will be look like this:
if (!partyDto.equals(cachedParty)) {
if (cachedParty == null && isActive(partyDto) || (cachedParty != null && isActive(cachedParty) && !isActive(partyDto)) {
pricingControlList.add(convertPartyDtoToPricingControl(partyDto));
}
partyCache.put(partyDto.getSellerServicerNumber(), partyDto);
partiesToSaveOrUpdate.add(partyDto);
}

Related

Intellij says that this can be a Null-Pointer. But according javadoc

private boolean checkStatusAct(Contract contract) {
if (contract.getActs() == null || contract.getActs().isEmpty()) {
return true;
} else if (contract.getActs() != null || (!contract.getActs().isEmpty())) { //here
for (ContractAct contractAct : contract.getActs()) {
if (contractAct.getStatusId() == 15) {
return true;
}
}
}
return false;
}
Isn't it successively checked one by one and if it's not null (!= null || .isEmpty()) it never produces a NullPoi
In Jav 8 or higher version. Assuming contract.getActs() is a list. You don't need to write else: You can do like
private boolean checkStatusAct(Contract contract) {
if (contract.getActs() == null || contract.getActs().isEmpty()) {
return true;
}
return contract.getActs().stream().anyMatch(c -> c.getStatusId() == 15);
}
The problem is that
contract.getActs() != null || (!contract.getActs().isEmpty())
will throw a NullPointerException if contract.getActs() returns null. In that case contract.getActs() != null is false and because of the || operator the JVM must evaluate contract.getActs().isEmpty() which will throw the NullPointerException.
To correct this you should write
contract.getActs() != null && (!contract.getActs().isEmpty())
But this is effectively not needed, because your first if condition already handles the cases where contract.getActs() or contract.getActs().isEmpty(). It would be better to rewrite your code as
private boolean checkStatusAct(Contract contract) {
if (contract.getActs() == null || contract.getActs().isEmpty()) {
return true;
} else {
for (ContractAct contractAct : contract.getActs()) {
if (contractAct.getStatusId() == 15) {
return true;
}
}
}
return false;
}
Starting from Java 8 you can also use streams (navnath's solution).

How do i combine condition statements with this particular lambda expression?

I have a java method written using lambda expressions where i need to add more conditions, and i was forbidden from using classical if and elses. This is my current code that checks if getInstrument has the correct ENUM:
public static Predicate<Deal> isDeal() {
return i ->
i.getInstrument() == ENUM1
|| i.getInstrument() == ENUM2
|| i.getInstrument() == ENUM3;
}
To this code, i need to add a condition that checks if i.getGroup() is null and and then keep checking if the enums are correct. I also need to add a condition that, if i.getGroup() != null and i.getGroup() != "NODEAL" and i.getInstrument() is not an ENUM2 or ENUM3, it returns i. This is how i would write it with classical if and elses:
public static Predicate<Deal> is Deal() {
if ( i.getGroup() == null && i.getInstrument() == ENUM1
|| i.getInstrument() == ENUM2
|| i.getInstrument() == ENUM3) {
return i;
} else if ( i.getGroup() != null && i.getGroup() == "DEAL" &&
i.getInstrument() != ENUM2 || i.getInstrument() != ENUM3) {
return i;
}
}
How could i write this using lambda?
something like
Predicate<Deal> isDeal() {
return deal -> deal.getGroup() == null
&& EnumSet.of(Instrument.ENUM1,
Instrument.ENUM2,
Instrument.ENUM3)
.contains(deal.getInstrument())
||
"DEAL".equals(deal.getGroup())
&& !EnumSet.of(Instrument.ENUM2,
Instrument.ENUM3)
.contains(deal.getInstrument())
}
Something like this
public static Predicate<Deal> isDeal() {
return i->
(i.getGroup() == null
&& (i.getInstrument() == ENUM1
|| i.getInstrument() == ENUM2
|| i.getInstrument() == ENUM3)
)
||
( i.getGroup() != null
&& i.getGroup() == "DEAL"
&& i.getInstrument() != ENUM2 && i.getInstrument() != ENUM3);
}
PS: Keep in mind that you should compare string with equals not ==.
I don't know your business domain, but I tried to make the condition more expressive, readable and maintainable. I would also ask the client why they want it with lambdas because I see no reason to use them here. An if-else statement would give you the same without the overhead.
public Predicate<Deal> isDeal() {
return isGroupAbsent().or(isGroupPresent());
}
private Predicate<Deal> isGroupPresent() {
Instrument i = i.getInstrument();
return d -> "DEAL".equals(d.getGroup()) && i != ENUM2 && i != ENUM3;
}
private Predicate<Deal> isGroupAbsent() {
Instrument i = i.getInstrument();
return d -> d.getGroup() == null && (i == ENUM1 || i == ENUM2 || i == ENUM3);
}
This is a perfect job for the ternary operator ? :
But there still is a problem with your last condition, what should it return, true or false ? Knowing the Predicate<T> signature is boolean test(T t);
public static Predicate<Deal> isDeal() {
return i-> i.getGroup() == null ?
EnumSet.of(ENUM1, ENUM2, ENUM3).contains(i.getInstrument()) :
!"DEAL".equals(i.getGroup()) ?
!EnumSet.of(ENUM2, ENUM3).contains(i.getInstrument()) :
false; // What do you put here? This is missing in your question
}

Check two arguments for null in an elegant way

I am iterating over two collections and check if both collections contain
the same elements. I can't use Java 8.
edit 1 year after:
I created the method in the question to check if two Collections contain the same elements, without thinking about the fact that I am passing two Collection implementations into the method.
But Collection does not determine how elements are sorted. And I am iterating over the collections. Thus, some implementation of Collection could save elements in random order, while containing the same elements.
Both collections contain elements that are comparable and the content
is defined as equal, if all elements return a x.compareTo(y) with 0.
Two values are defined as different, if one of them is null, but not the other.
I want to find an elegant way to compare on nullity and prevent
a null check on the final compareTo().
My current implementation:
public static <T extends Comparable<T>> boolean isSame(#Nullable Collection<T> a, #Nullable Collection<T> b) {
if (a == null || b == null) {
return (a == null && b == null);
}
if (a.size() != b.size()) {
return false;
}
Iterator<T> aIt = a.iterator();
Iterator<T> bIt = b.iterator();
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
//both null, don't compare, continue looping...
} else if (aValue.compareTo(bValue) != 0) {
return false;
}
}
return true;
}
I want to continue the while loop, if both values are null, because that is
defined as equal.
But I am struggling with this part:
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
}
Question:
Is there a more elegant and readable way to compare on nullity, do a further compare if both are not null, return false if only one is null, and continue the loop, if both values are null?
The sequence as follows should work well:
if(aValue == null && bValue == null) continue; // both null; continue
if(aValue == null || bValue == null) return false; // any null; return false
if(aValue.compareTo(bValue) != 0) { // both non-null; compare
return false;
}
In Java8, you can build a Comparator that would replace comparison sequence at cost of creating an extra object (you will need to decide if you care about that):
Comparator<T> cmp = Comparator.nullsLast(Comparator.naturalOrder());
The compararor will take care of null comparison for you (since you assume that two nulls are equal):
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (cmp.compare(aValue, bValue) != 0) {
return false;
}
}

How to handle null values when doing Collections.sort() with nested objects?

What is the best way to deal with null values, when doing Collections.sort() on nested objects?
I'd like to sort a couple of objects, basically applying this rule:
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
However, any of these objects can be null (i.e. invoice position, invoice and invoice number).
public class InvoicePos {
private Invoice invoice = null;
// ...
}
public class Invoice {
private String invoiceNo = "";
// ...
}
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
For clarification: I'm aware that my above example may raise NullPointerExceptions. Currently I'm doing the following and basically, I questioned myself, if there is any smarter approach.
Collections.sort(allInvoicePositions, new Comparator<InvoicePos>() {
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
if (null == invoicePosOne && null == invoicePosTwo) {
return 0;
}
if (null == invoicePosOne) {
return -1;
}
if (null == invoicePosTwo) {
return 1;
}
if (null == invoicePosOne.getInvoice() && null == invoicePosTwo.getInvoice()) {
return 0;
}
if (null == invoicePosOne.getInvoice()) {
return -1;
}
if (null == invoicePosTwo.getInvoice()) {
return 1;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo() && null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 0;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo()) {
return -1;
}
if (null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 1;
}
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
});
There is something called as NullComparator in org.apache.commons.collections.jar.
This might help you https://commons.apache.org/proper/commons-collections/javadocs/api-2.1.1/org/apache/commons/collections/comparators/NullComparator.html.
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
If these values don't represent anything in your collection, then the best thing you can do is avoid them; don't allow inserting them, so you won't have to handle them when comparing items.
If you insist to have them, then you must check if they're null to avoid NullPointerException.
If you have null values then you need to handle them explicitly and in a consistent way so to have a valid ordering relation. That is, something like:
compare (a, b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return +1;
return comp(a,b);
}
Don't be tempted to do something like:
compare (a, b) {
if (a == null || b == null) return -1;
return comp(a,b);
}
which would break the ordering relation.

“Comparison method violates its general contract!” : java 7 error with Date data

I have found this issue in multiple threads and tried suggested replies. But didn't get success.
My code is mentioned below:
#Override
public int compareTo(CustomObject o) {
try {
if (getOriginalActionDate() == null || o.getOriginalActionDate() == null) {
return -1;
}
return new SimpleDateFormat("MM/dd/yyyy").parse(
getOriginalActionDate()).compareTo(
new SimpleDateFormat("MM/dd/yyyy").parse(o
.getOriginalActionDate()));
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
Please let me know what mistake I am doing here? Any pointer in this regard will be very helpful.
Thanks,
Gopal lal
When both Dates are null, you should return 0 instead of -1.
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)
For the code posted, when Date in both the objects are null
x.compareTo(y) == y.compareTo(x) == -1
and this violates the contract.
To fix the method, change the if for null check to:
if (getOriginalActionDate() == null && o.getOriginalActionDate() == null) {
return 0;
} else if (getOriginalActionDate() == null) {
return -1;
} else if (o.getOriginalActionDate() == null) {
return 1;
}
So if both are null, the return value would be 0 (equal), otherwise the null would be regard as the smaller object.

Categories