I am using this code to sort items by date:
Collections.sort(productList, (d1, d2) -> {
if (d1.getDateExpired() == null && d2.getDateExpired() == null) {
return 1;
} else if (d1.getDateExpired() == null && d2.getDateExpired() != null) {
return 1;
} else if (d1.getDateExpired() != null && d2.getDateExpired() == null) {
return -1;
} else {
return d1.getDateExpired().compareTo(d2.getDateExpired());
}
})
I know there are some answers, but i cannot understand the bug, especially that I am cannot reproduce the issue, it happen to 2 user out of ~300.
Related
I am new to Java, I am bored with if else statement I want to
refactor my code and relief from if-else statement, not I am not able
to reduce my code, In my code nothing is static every thing comes
from user side. I share my codes for your reference.
if (orderDetail != null && item != null && !orderDetail.isUnitPriceModified()) {
ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());
if (origin != null && (origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev")))) {
RepGroupManufacturer repGroupManufacturer = repGroupManufacturerRepository.findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);
if (repGroupManufacturer != null && repGroupManufacturer.getB2bItemPricingPolicy() != null && repGroupManufacturer.getB2bItemPricingPolicy().equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE)) {
if (orderDetail.getItemSCSID() == null && item.getRetailPrice() != null) {
orderDetail.setUnitPrice(item.getRetailPrice());
} else {
// ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());
if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() != null) {
orderDetail.setUnitPrice(itemSizeColorStyle.getRetailPrice());
} else if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() != null) {
orderDetail.setUnitPrice(item.getRetailPrice());
} else if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() == null) {
throw new NullPointerException("item price can not be null.");
}
}
}
}
How to convert this if else to map.
Since i dont know what types you are returning and what type of objects some variables are i had to improvise but this should still work you just need to change to the correct values
public static void main(String[] args) {
setUnitPrice(orderDetail,origin);
}
public static void setUnitPrice(OrderDetail orderDetail,Origin origin){
if (orderDetail == null && item == null && orderDetail.isUnitPriceModified()) return;
if (origin == null && !origin.contains("b2baccess") ||
!origin.contains(".myappdev") && origin.contains("apps.myappdev")) return;
RepGroupManufacturer repGroupManufacturer = repGroupManufacturerRepository
.findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);
if (repGroupManufacturer == null &&
repGroupManufacturer.getB2bItemPricingPolicy() == null &&
!repGroupManufacturer.getB2bItemPricingPolicy().equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE)) return;
ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());
orderDetail.setUnitPrice(getUnitPrice(itemSizeColorStyle,item,orderDetail));
}
public static int getUnitPrice(ItemSizeColorStyle itemSizeColorStyle, Item item, OrderDetail orderDetail) {
if (orderDetail.getItemSCSID() == null && item.getRetailPrice() != null) return item.getRetailPrice();
if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() != null) return itemSizeColorStyle.getRetailPrice();
if (itemSizeColorStyle != null && itemSizeColorStyle.getRetailPrice() == null && item.getRetailPrice() != null) return item.getRetailPrice();
throw new NullPointerException("item price can not be null.");
}
At-least break into multiple small methods to start with. This will make if-else less scary, easy to understand.
Also there are areas / paths to avoid duplicate checks.
Maybe you could break responsibility of validation checks into different classes as well.
import java.util.Optional;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
class Scratch {
private static String NOT_DELETED = "not-deleted";
private ItemSizeColorStyleRepository itemSizeColorStyleRepository;
private RepGroupManufacturerRepository repGroupManufacturerRepository;
public void setUnitPrice(OrderDetail orderDetail, Item item, String origin, Integer repGroupID, Integer manufacturerID) {
if (isValidOrderDetail(orderDetail) && nonNull(item)) {
if (isValidOrigin(origin)) {
if (isValidRepGroupManufacturer(repGroupID, manufacturerID)) {
if (isNull(orderDetail.getItemSCSID()) && nonNull(item.getRetailPrice())) {
orderDetail.setUnitPrice(item.getRetailPrice());
} else {
ItemSizeColorStyle itemSizeColorStyle = itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID());
if (nonNull(itemSizeColorStyle)) {
if (nonNull(itemSizeColorStyle.getRetailPrice())) {
orderDetail.setUnitPrice(itemSizeColorStyle.getRetailPrice());
} else {
if (nonNull(item.getRetailPrice())) {
orderDetail.setUnitPrice(item.getRetailPrice());
} else {
throw new NullPointerException("item price can not be null.");
}
}
}
}
}
}
}
}
private boolean isValidOrderDetail(OrderDetail orderDetail) {
return Optional
.ofNullable(orderDetail)
.map(e -> !e.isUnitPriceModified())
.orElse(false);
}
private boolean isValidOrigin(String origin) {
return nonNull(origin) &&
(origin.contains("b2baccess") || (origin.contains(".myappdev") && !origin.contains("apps.myappdev")));
}
private boolean isValidRepGroupManufacturer(Integer repGroupID, Integer manufacturerID) {
RepGroupManufacturer repGroupManufacturer = repGroupManufacturerRepository
.findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);
return Optional
.ofNullable(repGroupManufacturer)
.flatMap(e -> Optional.ofNullable(e.getB2bItemPricingPolicy()))
.map(e -> e.equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE))
.orElse(false);
}
}
Note: I have assumed certain datatypes, which I don't have any impact on overall solution.
Some if-else statements express business logic which should be anything but boring. The code you posted appears to contain at least some business logic but the manner in which it is written makes it difficult to read and maintain.
There are some rules I follow when refactoring this type of code:
"positive thinking" - avoid if not statements, that is what else is for.
replace nested if-statements with functions.
be as lazy as possible, only lookup values when needed.
use variable names that have a meaning.
On 1, replace this
if (x is not null) {
// more code
}
with
if (x is null) {
return;
}
// more code
On 2, replace this
if (x > 1 ) {
// lots of code
}
with
if (x > 1) {
updateStuff(x);
}
function updateStuff(int x) {
// lots of code
}
This also opens up the opportunity to let the function return a value that can be used further on.
On 3, replace this
x = queryDatabase(y);
if (y > 1) {
// use x
}
with
if (y > 1) {
x = queryDatabase(y);
// use x
}
Finally, on 4, I sometimes introduce boolean values to convey meaning to complex conditions. E.g. compare this:
if ((x < 1 and y > 100) || (z not 0 and y < 1)) {
// do stuff
}
with
boolean findPrice = (x < 1 and y > 100);
boolean findProduct = (z not 0 and y < 1);
if (findPrice || findProduct) {
// do stuff
}
When all these rules are applied it becomes much easier to read the code and also easier to maintain and (unit) test the code.
Disclaimer: it merely impossible to reimplement a chunk of code containing so much logic and guaranty that you can simply copy-past it, and it would work just fine.
The very first advice I can give to change the return type in your Repositories and leverage the Optional API (that alone wouldn't resolve all the issues, but it would give some room for improvement).
Secondly, you need to break presented logic into self-contained meaningful peaces and give them names. The current code violates the first principle of SOLID - Single responsibility principle in a very obvious way. How can you test it, or how can change this functionality without rewriting from scratch? Such code is very hard to maintain.
Here's my attempt to reimplement this logic, assuming that both Repositories would produce an Optional as a result:
public void foo(OrderDetail orderDetail, Item item) {
if (!isValid(orderDetail, item, origin)) return;
repGroupManufacturerRepository
.findByRepGroupIDAndManufacturerIDAndRecordDeleted(repGroupID, manufacturerID, NOT_DELETED);
.filter(manufacturer -> manufacturer.getB2bItemPricingPolicy() != null)
.filter(manufacturer -> manufacturer.getB2bItemPricingPolicy().equalsIgnoreCase(ReptimeConstants.SHOWRETAILPRICE))
.ifPresent(manufacturer -> itemSizeColorStyleRepository.findByRecordID(orderDetail.getItemSCSID())
.filter(itemStyle -> itemSizeColorStyle.getRetailPrice() != null)
.ifPresent(itemStyle -> {
if (needToApplyItemPrice(orderDetail, item, itemStyle)) orderDetail.setUnitPrice(item.getRetailPrice());
else if (needToApplyItemStylePrice(orderDetail, item, itemStyle)) orderDetail.setUnitPrice(item.getRetailPrice());
else throw new NullPointerException("item price can not be null.");
})
);
}
public boolean isValid(OrderDetail orderDetail, Item item, Origin origin) {
return orderDetail != null && item != null && !orderDetail.isUnitPriceModified()
&& origin != null
&& (origin.contains("b2baccess") || origin.contains(".myappdev") && !origin.contains("apps.myappdev"));
}
public boolean needToApplyItemPrice(OrderDetail orderDetail, Item item, ItemSizeColorStyle itemStyle) {
return (orderDetail.getItemSCSID() == null || itemStyle.getRetailPrice() == null)
&& item.getRetailPrice() != null;
}
public boolean needToApplyItemStylePrice(OrderDetail orderDetail, Item item, ItemSizeColorStyle itemStyle) {
return !(orderDetail.getItemSCSID() == null && item.getRetailPrice() != null)
&& itemStyle.getRetailPrice() != null;
}
I am trying to avoid if else conditions can you guys please help me?
if (getFromDate() != null && getToDate() != null && getBranchId() != null && getServiceGroupId() != null) {
return something;
} else if (getFromDate() != null && getToDate() != null && getBranchId() != null && getServiceGroupId() == null) {
return something;
} else if (getFromDate() != null && getToDate() != null && getServiceGroupId() != null && getBranchId() == null) {
return something;
} else if (getServiceGroupId() != null && getBranchId() != null && getFromDate() == null && getToDate() == null) {
return something;
} else if (getServiceGroupId() == null && getBranchId() == null && getFromDate() != null && getToDate() != null) {
return something;
} else if (getFromDate() == null && getToDate() == null && getBranchId() == null && getServiceGroupId() != null) {
return something;
} else if (getFromDate() == null && getToDate() == null && getBranchId() != null && getServiceGroupId() == null) {
return something;
} else {
return something;
}
You can use Stream.allMatch(x -> x == null) to check for mutiple null values from different or similar types. Declare Stream variables (or an array) using Stream.of(T... values).
It is best declared on some function boolean foo(T... varargs).
I see the following pattern in your code:
You have a group of boolean conditions (some value being null vs. not null) and want to return different values based on specific true/false combinations of these conditions.
If you encounter this pattern at multiple places, it might be worth to introduce a supporting class. Let's call it MultiBoolean, so you can write:
MultiBoolean nullCombinations = new MultiBoolean(
getFromDate() == null,
getToDate() == null,
getBranchId() == null,
getServiceGroupId() == null);
if (nullCombinations.matches(false, false, false, false) {
return something;
} else if (nullCombinations.matches(false, false, false, true) {
return something;
} else if (...) {
// and so on
The class might roughly look like:
public class MultiBoolean {
private boolean[] conditions;
public MultiBoolean(boolean... conditions) {
this.conditions = conditions;
}
public boolean matches(boolean... pattern) {
return Arrays.equals(conditions, pattern);
}
}
Disclaimer: I didn't test it.
I am a beginner trying to write a function in Java that returns true if two passed 2D arrays of int type are the same size in every dimension, and false otherwise. Requirements are that if both arrays are null you should return true. If one is null and the other is not you should return false.
Somehow getting an error for my code:
public static boolean arraySameSize(int[][] a, int[][] b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a.length == b.length) {
for (int i = 0; i < a.length; i++) {
if (a[i].length == b[i].length) {
return true;
}
}
}
return false;
}
Any help would be appreciated!
Edit: Problem is "Runtime Error: null"
Your logic looks almost spot-on already. The only issue I see is in the logic handling the case where both arrays are not null and have the same first dimension. You should be returning false if any index does not have matching lengths:
public static boolean arraySameSize(int[][] a, int[][] b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a.length != b.length) {
return false;
}
// if the code reaches this point, it means that both arrays are not
// null AND both have the same length in the first dimension
for (int i=0; i < a.length; i++) {
if (a[i] == null && b[i] == null) {
continue;
}
if (a[i] == null || b[i] == null) {
return false;
}
if (a[i].length != b[i].length) {
return false;
}
}
return true;
}
Follow the demo link below to see some of examples of this method working correctly.
Demo
I am getting the below error
Unable to resume activity {com.xxx.yyy.zzz.HomeActivity}: java.lang.IllegalArgumentException: Comparison method violates its general contract!
I am handling null cases for the string even then this error is coming. Any hints on what may be wrong. Code below
public class ConversationComparer implements Comparator<Conversation> {
#Override
public int compare(Conversation x, Conversation y) {
if (x.getLastMessageDate() == null) {
return 1;
}
if (y.getLastMessageDate() == null) {
return -1;
}
return y.getLastMessageDate().compareTo(x.getLastMessageDate());
}}
public java.util.Date getLastMessageDate() {
return lastMessageDate;
}
This is how i use the comparator
if (conversationListAdapter != null) {
Collections.sort(this.list,new ConversationComparer());
conversationListAdapter.notifyDataSetChanged();
}
You should also check x and y again null and return 0 if both are null.
#Override
public int compare(Conversation x, Conversation y) {
if (x == y || (x != null && y != null && x.getLastMessageDate() == y.getLastMessageDate()))
return 0;
if (x == null)
return 1;
if (y == null)
return -1;
if (x.getLastMessageDate() == null)
return 1;
if (y.getLastMessageDate() == null)
return -1;
return y.getLastMessageDate().compareTo(x.getLastMessageDate());
}
Also, it would be interesting to know what data type "getLastMessageDate()" returns.
The only thing I can see that's wrong with it is you don't correctly handle the case where x.getLastMessageDate() and y.getLastMessageDate() are both null.
I think if you add this line to the beginning of the method it meets the contract.
if (x.getLastMessageDate() == null && y.getLastMessageDate() == null)
return 0;
I've been asked to write a recursive method to investigate whether or not there are any single children. I have get the base cases but am a bit confused about how to go about the recursive section as I will need to investigate both the right and the left subtree and return false if one of them has a single child and true if one of them has 0 children or recur.
what I have so far is:
public static boolean noSingleChildren( BinaryTreeNode t ) {
if (rightC == null || leftC == null) {
return false;
} else if (rightC == null && leftC == null) {
return true;
} else {
return............
}
}
The logic is quite simple:
If the current node only has a single child, you're done.
Otherwise, recursively ask each non-null child the same question, and combine the answers using logical "or".
Since this looks like homework, I leave the implementation to you.
public static boolean noSingleChildren( BinaryTreeNode t ) {
if (rightC == null || leftC == null) {
return false;
} else if (rightC == null && leftC == null) {
return true;
} else {
return noSingleChildren(t.getLeftBranch()) || noSingleChildren(t.getRightBranch());
}
}
Ho, I love trees questions:
public static boolean hasSingleChildren( BinaryTreeNode t ) {
if (t == null) {
return false;
} else if (t.rightC == null && t.leftC != null) {
return true;
} else if (t.rightC != null && t.leftC == null) {
return true;
} else {
return hasSingleChildren(t.rightC) || hasSingleChildren(t.leftC);
}
}