Java - Node search optimization and performance - java

I need to search for 7 ID and if 1 is found return this Node. As I can't find any way to search for id.contains I made the code below that meets my need. But it hurts my eyes to look at it. Is there a way to optimize this code ??
As for performance, would it be necessary to use something like node.recycle() in the List to avoid overloading ???
private AccessibilityNodeInfo searchID() {
AccessibilityNodeInfo node = getRootInActiveWindow();
if (node != null) {
List<AccessibilityNodeInfo> id1 = node.findAccessibilityNodeInfosByViewId("com....:id/id1");
List<AccessibilityNodeInfo> id2 = node.findAccessibilityNodeInfosByViewId("com....:id/id2");
List<AccessibilityNodeInfo> id3 = node.findAccessibilityNodeInfosByViewId("com....:id/id3");
List<AccessibilityNodeInfo> id4 = node.findAccessibilityNodeInfosByViewId("com....:id/id4");
List<AccessibilityNodeInfo> id5 = node.findAccessibilityNodeInfosByViewId("com....:id/id5");
List<AccessibilityNodeInfo> id6 = node.findAccessibilityNodeInfosByViewId("com....:id/id6");
List<AccessibilityNodeInfo> id7 = node.findAccessibilityNodeInfosByViewId("com....:id/id7");
if (id1 != null && !id1.isEmpty()) {
return id1.get(0);
} else if (id2 != null && !id2.isEmpty()) {
return id2.get(0);
} else if (id3 != null && !id3.isEmpty()) {
return id3.get(0);
} else if (id4 != null && !id4.isEmpty()) {
return id4.get(0);
} else if (id5 != null && !id5.isEmpty()) {
return id5.get(0);
} else if (id6 != null && !id6.isEmpty()) {
return id6.get(0);
} else {
if (id7 != null && !id7.isEmpty()) {
return id7.get(0);
}
}
}
return null;
}

Related

LeetCode tree question no. 872 (leaf similar trees)

class Solution {
static ArrayList<Integer> leaves1 = new ArrayList<Integer>();
static ArrayList<Integer> leaves2 = new ArrayList<Integer>();
public boolean leafSimilar(TreeNode root1, TreeNode root2) {
if(root1.left == null && root1.right == null && root2.left == null && root2.right == null)
{
if(root1.val == root2.val)
return true;
else
return false;
}
leafmethod1(root1);
leafmethod2(root2);
if (leaves1.size() != leaves2.size())
return false;
for(int k=0;k<leaves1.size();k++)
{
if(leaves1.get(k) != leaves2.get(k))
return false;
}
return true;
}
public void leafmethod1(TreeNode root)
{
if(root!=null && root.left==null && root.right==null)
{
leaves1.add(root.val);
}
if(root!=null)
{
if(root.left != null)
{
leafmethod1(root.left);
}
if(root.right != null)
{
leafmethod1(root.right);
}
}
}
public void leafmethod2(TreeNode root)
{
if(root!=null && root.left == null && root.right == null)
{
leaves2.add(root.val);
}
if(root!=null)
{
if(root.left != null)
{
leafmethod2(root.left);
}
if(root.right != null)
{
leafmethod2(root.right);
}
}
}
}
This is the code I wrote. But it's not running for some particular case like eg; root1 = [1,2] and root2 = [2, 2]. It seemed to work for all other big cases but only in small cases like eg; root1 =[1] and root2 = [1] it's giving me wrong answer.
I don't know where I am going wrong. Kindly help.

How to reduce cyclomatic complexity of this java method

I have the next java implementation, but it has a SonarQube issue and i don't know how to reduce the method.
if (user.getUserId() != null && user.getEmail() != null
&& user.getName() != null) {
return 1;
} else if (user.getUserId() != null && user.getEmail() != null) {
return 2;
} else if (user.getUserId() != null && user.getName() != null) {
return 3;
} else if (user.getUserId() != null) {
return 4;
} else if (user.getEmail() != null && user.getName() != null) {
return 5;
} else if (user.getName() != null) {
return 6;
} else if (user.getEmail() != null) {
return 7;
} else {
return 0;
}
when the user is a Pojo of Users
class Users {
String userId;
String email;
String name;
//getters and setters...
}
This is the real code and issue in SonarQube:
what about Pattern of Chain of Responsibility.
public abstract class Handler {
protected Handler next;
public abstract Integer process(User user);
}
Handler checkIdEmailName = new Handler() {
#Override
public Integer process(User user) {
boolean check = false;
if (check) {
return 1;
}else {
return next.process(user);
}
}
};
Handler checkIdEmail = new Handler() {
#Override
public Integer process(User user) {
boolean check = false;
if (check) {
return 1;
}else {
return next.process(user);
}
}
};
checkIdEmailName.next = checkIdEmail;
Integer result = checkIdEmailName.process(new User());
Break it to another methods would reduce the complexity of the method itself.
Something like
if (user.getUserId() != null && user.getEmail() != null
&& user.getName() != null) {
return 1;
} else if (user.getUserId() != null && user.getEmail() != null) {
return 2;
} else if (user.getUserId() != null && user.getName() != null) {
return 3;
} else if (user.getUserId() != null) {
return 4;
} else {
return yourNewMethod();
}
private int yourNewMethod(User user) {
if (user.getEmail() != null && user.getName() != null) {
return 5;
} else if (user.getName() != null) {
return 6;
} else if (user.getEmail() != null) {
return 7;
} else {
return 0;
}
}
so first of all we should emphasis what cognitive complexity is all about, and how it would make sense to reduce it. Mainly by extracting things which belongs together.
When taking a look at your method with the first 4 conditions, they share a similarity, and it is the check for userId. This means you can easily combine the checks below into one branch. Which will be easier to grasp, and also offers a nice way for extraction
if (user.getUserId() != null) {
if (user.getEmail() != null
&& user.getName() != null) {
return 1;
} else if (user.getEmail() != null) {
return 2;
} else if (user.getName() != null) {
return 3;
} else {
return 4;
}
} else if (user.getEmail() != null && user.getName() != null) {
return 5;
} else if (user.getName() != null) {
return 6;
} else if (user.getEmail() != null) {
return 7;
} else {
return 0;
}
Based on this you can further extract easily like
if (user.getUserId() != null) {
return fancyNameForAdditionalUserIdChecks(user);
} else if (user.getEmail() != null && user.getName() != null) {
return 5;
} else if (user.getName() != null) {
return 6;
} else if (user.getEmail() != null) {
return 7;
} else {
return 0;
}
private int fancyNameForAdditionalUserIdChecks(Users user) {
if (user.getEmail() != null
&& user.getName() != null) {
return 1;
} else if (user.getEmail() != null) {
return 2;
} else if (user.getName() != null) {
return 3;
} else {
return 4;
}
}
Now we only have four main branches in the first if - a developer who does not care about cases where the userid is null, can simple skip it, and he will not need to process all those branches. Where as if needs to, he has only one condition to first check, and the rest is easier to grasp.
To handle such a case, you always should think about, how somebody is reading code. What benefit he gets, and were you can reduce the cognitive load so it will gets easier for the following developer to understand. Machines will never have problem reading our code, but writing code which is easy to read by humans, that is the hard part.
Sidenote:
i would rather rework your Dao methods, and in this case put that logic into the dao, by providing a map of paramaters to the dao, and let the dao handle such a logic. like dao.find(Map<String, Object> params) and you could handle this based on the fields available or not available.
Here is the reduce complexity code,
boolean userIdAvailable = user.getUserId() != null;
boolean emailAvailable = user.getEmail() != null;
boolean nameAvailable = user.getName();
short response = checkAll(userIdAvailable, emailAvailable, nameAvailable);
if (response == 0) {
response = checkEmailAndName(emailAvailable, nameAvailable);
if (response == 0) {
checkUserIdAndName(userIdAvailable, nameAvailable);
}
}
short checkAll(boolean userIdAvailable, boolean emailAvailable, boolean nameAvailable) {
return userIdAvailable && emailAvailable && nameAvailable ? 1 : 0;
}
short checkEach(boolean userIdAvailable, boolean emailAvailable, boolean nameAvailable) {
short response = 0;
if(userIdAvailable) {
response = 4;
} else if(emailAvailable) {
response = 7;
} else if(nameAvailable) {
response = 6;
}
return response;
}
short checkUserIdAndEmail(boolean emailAvailable, boolean userIdAvailable) {
return userIdAvailable && emailAvailable ? 2 : 0
}
short checkEmailAndName(boolean emailAvailable, boolean nameAvailable) {
return emailAvailable && nameAvailable ? 5 : 0
}
short checkUserIdAndName(boolean userIdAvailable, boolean nameAvailable) {
return userIdAvailable && nameAvailable ? 3 : 0
}

Java, convert Ternary operator to IF ELSE

I am sure this repeats something, but yet due to short time I have to ask you straight forward help.
How to convert Ternary (: and ?) operator into IF-ELSE statement in Java?
public Integer get(Integer index) {
if (first == null) {
return null;
}
MyNode curNode = first;
while (index >= 0) {
if (index == 0) {
return curNode == null ? null : curNode.getValue();
} else {
curNode = curNode == null ? null : curNode.getNext();
index--;
}
}
return null;
}
What I did tried, but it gave me wrong output (this is all about LinkedList) is modifying it to:
while (index >= 0) {
if (index == 0) {
// pre-modified -> return curNode == null ? null : curNode.getValue();
if (first == null) {
return null;
} else {
return curNode.getValue();
}
} else {
if (curNode != null) {
return curNode.getNext().getValue();
//return null;
} else {
return null;
}
// pre-modified -> curNode = curNode == null ? null : curNode.getNext();
// pre-modified -> index--;
}
}
In addition to that it was necessary also to fix part after else to:
else {
if (curNode != null) {
curNode = curNode.getNext();
index--;
//return null;
} else {
curNode = null;
}
// pre-modified -> curNode = curNode == null ? null : curNode.getNext();
// pre-modified -> index--;
}
Question solved.

Sorting using collections for multiple parameter with null values

I wanted to sort list of records in my using multiple comparators.
It contains null values as well for some fields.
I used java collections, to sort it, but it works only for one filed which is places at top.
My code:
Collections.sort(userListResult, new Comparator<UserDto>()
{
#Override
public int compare(UserDto userDto1, UserDto userDto2)
{
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
return -1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
return 1;
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() == null) {
return 0;
}
if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() != null) {
return 1;
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() == null) {
return -1;
}
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
}
if (userDto1.getLastName() != null && userDto2.getLastName() == null) {
return -1;
}
if (userDto1.getLastName() == null && userDto2.getLastName() != null) {
return 1;
}
if (userDto1.getFirstName().compareTo(userDto2.getFirstName()) != 0) {
return userDto1.getFirstName().compareTo(userDto2.getFirstName());
}
if (userDto1.getFirstName() != null && userDto2.getFirstName() == null) {
return -1;
}
if (userDto1.getFirstName() == null && userDto2.getFirstName() != null) {
return 1;
}
return 0;
}
});*/
I wanted to sort descending of LastLoginDate, LastActionDate. Either or both fields might be null in some cases.
And ascending of names. And to display all other null field values(LastLoginDate, LastActionDate) at last.
But when i sort, with this code it takes only the first defined method to sort.
Example, if i have 3 records having same, "LastLoginDate" then it should check sort with "LastActionDate" values. But its not sorted with this logic.
So i added another algorithm to sort, since some fields has null values it is not properly sorted.
My second logic:
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
compareLastLoginDate = userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
compareLastActionDate = userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
compareLastName = userDto1.getLastName().compareTo(userDto2.getLastName());
}
if (compareLastLoginDate == 0) {
return ((compareLastActionDate == 0) ? compareLastName : compareLastActionDate);
}
else {
return compareLastLoginDate;
}
Here i am getting the integer values to compare it "compareLastActionDate, compareLastName, compareLastLoginDate".
I used simple date format to filter the list.
Here is my working code,
public int compare(UserDto userDto1, UserDto userDto2) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
String Date1 = format.format(userDto1.getLastLoginDate());
String Date2 = format.format(userDto2.getLastLoginDate());
if (Date1.equals(Date2)) {
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
String Date3 = format.format(userDto1.getLastActionDate());
String Date4 = format.format(userDto2.getLastActionDate());
if (Date3.equals(Date4)) {
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
}
} else {
return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
}
} else {
return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
}
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
return -1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
return 1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() == null) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
} }
I would recommend you to use the java8 comparators, it provides some helpful methods to compare based in multiple attributes with thenComparing().
If you don't want to / can't use, try two wrap part of that repetitive code in one or multiple custom Comparator or in a helper method.
Here, for simplicity, the following helper method is used (in java8 you can use method references):
public static <R extends Comparable<? super R>> int nullSort(R r1, R r2,
boolean ascending,
boolean nullsFirst) {
R rs1 = ascending ? r1 : r2, rs2 = ascending ? r2 : r1;
if (rs1 != null && rs2 != null) return rs1.compareTo(rs2);
else if (r1 == null && r2 == null) return 0;
else if (r1 == null) return (nullsFirst ? -1 : 1);
else return (nullsFirst ? 1 : -1);
}
In your method, you could use this nullSort() method, to check first for lastLoginDate descending and nulls last (false, false), then lastActionDate again descending and nulls last.
A difference with your comparator is that you stop evaluating here when both are null. It would be better that when lastLoginDate and lastActionDate are nulls you keep ordering by lastName and firstName. If you don't want this, you can add if (result == 0) return 0; after the second if in the method below.
Then after the dates are compared, you compare lastName and then firstName both ascending and nulls last (true, false).
#Override
public int compare(UserDto dto1, UserDto dto2) {
int result;
if ((result = nullSort(dto1.getLastLoginDate(), dto2.getLastLoginDate(),
false, false)) != 0) return result;
if ((result = nullSort(dto1.getLastActionDate(), dto2.getLastActionDate(),
false, false)) != 0) return result;
if ((result = nullSort(dto1.getLastName(), dto2.getLastName(),
true, false)) != 0) return result;
if ((result = nullSort(dto1.getFirstName(), dto2.getFirstName(),
true, false)) != 0) return result;
return 0;
}

I need a better way to reduce the line of codes which has a lot of if statements with method calls in conditions

This is my code , I need to know if there is any way to reduce the number of lines in the program.
Since there is method calls involved in the if statements I cannot use enum to replace them.
public class AgreementQueryBuilder {
#SuppressWarnings("unchecked")
public static String searchQueryBuilder(FetchAgreementsModel agreementsModel,
#SuppressWarnings("rawtypes") List obj) {
StringBuilder selectQuery = new StringBuilder(
"select *,e.id as agreementid from eglams_agreement e left outer join eglams_rentincrementtype t on e.rent_increment_method=t.id where");
// if statement to check the arguments and build the where criteria
if (agreementsModel.getAgreementId() != null || agreementsModel.getAgreementNumber() != null
|| agreementsModel.getStatus() != null || agreementsModel.getTenantId() != null
|| (agreementsModel.getFromDate() != null && agreementsModel.getToDate() != null)
|| agreementsModel.getTenderNumber() != null || agreementsModel.getTinNumber() != null
|| agreementsModel.getTradeLicense_number() != null)
return null;
boolean isAllFieldsNull = true;
if (agreementsModel.getAgreementId() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.id=?");
isAllFieldsNull = false;
obj.add(agreementsModel.getAgreementId());
}
}
if (agreementsModel.getAgreementNumber() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.agreement_number=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.agreement_number=?");
obj.add(agreementsModel.getAgreementNumber());
}
if (agreementsModel.getStatus() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.status=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.status=?");
obj.add(agreementsModel.getStatus());
}
if (agreementsModel.getTenantId() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.tenant_id=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.tenant_id=?");
obj.add(agreementsModel.getTenantId());
}
if (agreementsModel.getTenderNumber() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.tender_number=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.tender_number=?");
obj.add(agreementsModel.getTenderNumber());
}
if (agreementsModel.getTinNumber() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.tin_number=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.tin_number=?");
obj.add(agreementsModel.getTinNumber());
}
if (agreementsModel.getTradeLicense_number() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.TradeLicense_number=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.TradeLicense_number=?");
obj.add(agreementsModel.getTradeLicense_number());
}
if (agreementsModel.getFromDate() != null) {
if (agreementsModel.getToDate() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" t.FromDate=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and t.FromDate=?");
obj.add(agreementsModel.getFromDate());
selectQuery.append(" and t.ToDate=?");
obj.add(agreementsModel.getToDate());
}
}
System.err.println(selectQuery);
return selectQuery.toString();
}
}
Look at your code:
if (agreementsModel.getAgreementId() != null || ... )
return null;
So we know that if getAgreementId() != null this method will return null and will not go any further. But right after that you write:
if (agreementsModel.getAgreementId() != null) {
selectQuery.append(" e.id=?");
isAllFieldsNull = false;
obj.add(agreementsModel.getAgreementId());
}
}
We know that this entire block can never be entered, because if getAgreementId() != null was true, the method would have already returned.
So, the short answer to your question is yes, you can make this code much shorter by removing all of the irrelevant blocks of code that will never be called.
The long answer is that you should fix and debug your code to ensure that it actually does what you expect it to do before worrying about whether you can make it shorter. I suspect that means that this if can be removed since it makes all the following blocks useless:
if (agreementsModel.getAgreementId() != null || agreementsModel.getAgreementNumber() != null
|| agreementsModel.getStatus() != null || agreementsModel.getTenantId() != null
|| (agreementsModel.getFromDate() != null && agreementsModel.getToDate() != null)
|| agreementsModel.getTenderNumber() != null || agreementsModel.getTinNumber() != null
|| agreementsModel.getTradeLicense_number() != null)
return null;
But only you can know how your code should work. I suggest testing it to make sure it works before asking how to make it shorter.
I saw that the conditional used to generate an SQL Query. I believe you should change this to more readable, shorter and maintainable code using mapper framework like MyBatis / Hibernate.
Sample of query with conditional using Mybatis below :
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
<!-- add another conditional to add extra filter -->
</select>
On the sample above, we can dynamically generate a query by checking the input bean Blog. If title not null, add title in the criteria,and if authoer is not null, also add author to the criteria, and so on.
Your code all follows the same pattern
if (agreementsModel.getAgreementNumber() != null) {
if (isAllFieldsNull == true) {
selectQuery.append(" e.agreement_number=?");
isAllFieldsNull = false;
} else
selectQuery.append(" and e.agreement_number=?");
obj.add(agreementsModel.getAgreementNumber());
}
Which is: if something isn't null, put that thing in a list; and append a string based on some flag; then set the flag to true.
You can write this as a method:
boolean yourMethod(Object obj, List<Object> objs, String clause, StringBuilder clauses, boolean flag) {
if (obj == null) return flag;
objs.add(obj);
if (!flag) clauses.append(" and ");
clauses.append(clause);
return false;
}
So, you can now replace the above snippet of your code with:
isAllFieldsNull = yourMethod(
agreementsModel.getAgreementNumber(),
obj,
" e.agreement_number=? ",
selectQuery,
isAllFieldsNull);
etc, for the subsequent fields.

Categories