how to avoid multiple if-else statements for vaildation in Java - java

I have lots of multiple if-else statements. For code optimization, I need to write one function for all if else logic. As of now my code structure is in below.
input request is in JSONObject(org.json.simple.JSONObject), which have more than 10 values.
String s = (String) inputObj.get("test");
String s1 = (String) inputObj.get("test");
String s2 = (String) inputObj.get("test");
String s3 = (String) inputObj.get("test");
if (s != null && s.trim().isEmpty()) {
if (s1 != null && s1.trim().isEmpty()) {
if (s2 != null && s2.trim().isEmpty()) {
if (s3 != null && s3.trim().isEmpty()) {
if (s4 != null && s4.trim().isEmpty()) {
........
} else {
return;
}
} else {
return;
}
} else {
return;
}
} else {
return;
}
} else {
return;
}
How to avoid this kind of looping and throw an error message in common method.
Advance thanks.

Consider adding all your strings to array or ArrayList of string, and looping thru each entry in it, and check them for null or emptiness.

You can try this.
void main() {
List<String> sList = new ArrayList<>();
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
for(String s : sList){
try {
checkString(s);
}catch (Exception e){
//log or print the exception, however you like
}
}
}
void checkString(String s) throws Exception{
if(s!= null && !s.trim().isEmpty()){
//doStuff
}else{
throw new Exception("String is null or empty !!!");
}
}
You should also check this out.

public class YourClass{
private boolean isBlankDataPresent(JSONObject inputObj, String[] keys) throws Exception {
for (String key : keys) {
String input = (String) inputObj.get(key);
if( input == null || input.trim().isEmpty())
throw new Exception(key +" is Empty");
}
return false;
}
public boolean validateData(JSONObject inputObj, String[] keys) throws Exception {
boolean isBlankDataPresent= isBlankDataPresent(inputObj, keys);
if (!isBlankDataPresent) {
// do Your Stuff and return true
}
}
}

public Integer checkIsEmapty(String checkingString){
if(checkingString != null && !checkingString.trim().isEmpty()){
return 1;
}
return 0;
}
public String method(){
String s ="";
String s1 = "hi";
String s2 = "java";
String s3 = null;
String s4 = null;
Integer s1i = checkIsEmapty(s);
Integer s2i = checkIsEmapty(s1);
Integer s3i = checkIsEmapty(s2);
Integer s4i = checkIsEmapty(s3);
Integer s5i = checkIsEmapty(s4);
Integer total = s1i + s2i + s3i + s4i + s5i;
switch (total){
case 1 :
// To DO
case 2 :
// To DO
}
}
in switch used to checking the value, U can pass binary and Integer also

Like #Emre Acre mentioned,
List<String> sList = new ArrayList<>();
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
boolean allDataValid = sList
.stream()
.allMatch(s -> s != null && s.trim().isEmpty());
if(allDataValid) {
......
} else {
return;
}

Related

Method refactoring to avoid to many npe checks

I have created the following method which returns a Triple of strings. However, I don't like the way I've written it because I think I've put in too many Npe checks making it unreadable.
private Triplet<String, String, String> getInfoFromTable(Person person) {
StringBuilder idWithText = new StringBuilder();
String idText;
Date time = null;
Level level;
Exercise exerciseRecord = getExercise(person);
if (exerciseRecord != null && exerciseRecord.getId() != null) {
if(exerciseRecord.getLevel1() != null && exerciseRecord.getLevel2() != null){
level = new Level(exerciseRecord.getLevel1(), exerciseRecord.getLevel2());
} else {
level = new Level("1", "1");
}
idText = getIdText(level, exerciseRecord.getId());
if(!Strings.isNullOrEmpty(idText)) {
idWithText = idWithText.append(exerciseRecord.getId()).append(" " + idText);
}
if (exerciseRecord.getTime() != null) {
time = exerciseRecord.getTime().toDate();
}
return new Triplet<>(idWithText.toString(), "1", formatTime(time));
}
return new Triplet<>("", "", "");
}
Ηow can I make the above code look simpler? I've seen a little use of Optional but I don't know if it's good to use them in my case. Could someone help with the method refactor?
You need to split the huge method into several simple, it will decrease complexity.
private Triplet<String, String, String> getInfoFromTable(Person person) {
Exercise exerciseRecord = getExercise(person);
if (exerciseRecord != null && exerciseRecord.getId() != null) {
return new Triplet<>(getIdWithText(exerciseRecord, getLevel(exerciseRecord)), "1", formatTime(exerciseRecord.getTime()));
}
return new Triplet<>("", "", "");
}
private String formatTime(LocalTime time) {
if (time == null) {
return "";
}
return formatTime(time.toDate());
}
private Level getLevel(Exercise exerciseRecord) {
Level level;
if(exerciseRecord.getLevel1() != null && exerciseRecord.getLevel2() != null){
level = new Level(exerciseRecord.getLevel1(), exerciseRecord.getLevel2());
} else {
level = new Level("1", "1");
}
return level;
}
private String getIdWithText(Exercise exerciseRecord, Level level) {
String idWithText = "";
String idText = getIdText(level, exerciseRecord.getId());
if(!Strings.isNullOrEmpty(idText)) {
idWithText = String.format("%s %s", exerciseRecord.getId(), idText);
}
return idWithText;
}

java compare multiple values and find best match

I need to find best matched employee salary in the DB records as:
Name: City: State:
A (null) (null)
A (null) DEL
(null) (null) (null)
A SAKET DEL
Match order should be:
1. NAME = name, STATE = state, CITY = city
2. NAME = name, STATE = state , CITY = NULL
3. NAME = name, STATE = NULL, CITY = NULL
4. NAME = NULL, STATE = NULL, CITY = NULL
Means if in a row where all attributes matches – it should be selected, if we do not have that kind of data we should go to next best option like select state and city as NULL, etc.
My code as below, is giving me correct results but I need a more efficient way.
private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
BigDecimal salary = null;
BigDecimal salaryWithState = null;
BigDecimal salaryWithName = null;
BigDecimal salaryWithNoMatch = null;
while (results.next()) {
String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;
BigDecimal salaryRslt = null;
if(results.getString("SALARY") != null){
salaryRslt = BigDecimal.valueOf(results.getDouble("SALARY"));
}
if(billerName != null && !billerName.equals("") && billerName.equals(request.getBillPaymentsalaryCalculateInfo().getBillerName())){
if(city != null && !city.equals("") && city.equals(request.getMsgRqHdr().getCity()) &&
state != null && !state.equals("") && state.equalsIgnoreCase(request.getMsgRqHdr().getstate())){
salary = salaryRslt;
break;
} else if((city == null || city.equals("")) && state != null && !state.equals("") &&
state.equalsIgnoreCase(request.getMsgRqHdr().getState())){
salaryWithState = salaryRslt;
} else if((city == null || city.equals("")) && (state == null || state.equals(""))){
salaryWithName = salaryRslt;
}
} else if((billerName == null || billerName.equals("")) && (city == null || city.equals("")) &&
(state == null || state.equals(""))){
salaryWithNoMatch = salaryRslt;
}
}
if(salary != null){
return salary;
} else if(salaryWithState != null){
salary = salaryWithState;
} else if(salaryWithName != null){
salary = salaryWithName;
} else if(salaryWithNoMatch != null){
salary = salaryWithNoMatch;
}
return salary;
}
EDIT: I dont want to use 3 extra variables: salaryWithState, salaryWithName, salaryWithNoMatch.
I want just to give the general idea how this can be implemented, so I haven't actually tested and checked if it will give you the right salary.
public BigDecimal getSalaryForBestMatch(ResultSet resultSet, PaymentSalaryInfo paymentSalaryInfo) {
Map<String, Supplier<String>> m1 = new HashMap<>();
m1.put("EMP_NAME", paymentSalaryInfo::getBillerName);
m1.put("STATE", paymentSalaryInfo::getState);
m1.put("CITY", paymentSalaryInfo::getCity);
Map<String, Supplier<String>> m2 = new HashMap<>();
m2.put("STATE", paymentSalaryInfo::getState);
m2.put("CITY", paymentSalaryInfo::getCity);
Map<String, Supplier<String>> m3 = new HashMap<>();
m3.put("CITY", paymentSalaryInfo::getCity);
Optional<String> salary = Optional.empty();
while(resultSet.next() && !salary.isPresent()) {
salary = apply(m1, resultSet);
//check salary and then apply(m2, resultSet) ....
}
return salary.isPresent() ? new BigDecimal(salary.get()) : null;
}
public Optional<String> apply(Map<String, Supplier<String>> filter, ResultSet resultSet) {
boolean allMatch = filter.entrySet().stream().allMatch(entry -> {
String value = resultSet.getString(entry.getKey());
return value != null && value.equals(entry.getValue().get());
});
return allMatch ? Optional.of(resultSet.getString("salary")) : Optional.empty();
}
I have written the same logic in a different way with using arrays. If your environment can afford to use arrays, you can use this code. But I have not tested the code.
private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
BigDecimal salary = null;
int matchCount = 0;
String rBillerName = request.getBillPaymentsalaryCalculateInfo().getBillerName();
String rCity = request.getMsgRqHdr().getCity();
String rState = request.getMsgRqHdr().getstate();
String [] truthArray = new String[] {rBillerName, rCity, rState};
while (results.next()) {
String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;
BigDecimal salaryRslt = results.getString("SALARY") != null ? BigDecimal.valueOf(results.getDouble("SALARY")): null;
String [] testArray = new String[] {billerName, city, state};
int localMatchCount = 0;
for(int i = 0; i < testArray.length; i++) {
if(testArray[i] != null && testArray[i].equals(truthArray[i]))
localMatchCount++;
else {
break;
}
}
if(localMatchCount >= matchCount){
matchCount = localMatchCount;
salary = salaryRslt;
}
}
return salary;
}

How do I prevent an IndexOutOfBoundsException error in this Java code?

Basically I just want an error message when there are no more records to show in the array list. What do I need to tweak?
public void nextRecord()
{
if(records.size() > 0)
{
recordCount++;
if(records.get(recordCount) != null)
{
String[] array = records.get(recordCount).split(",");
String item = array[0].trim().replaceAll("\"", "");
String number = array[1].trim();
String cost = array[2].trim();
String amnt = array[3].trim();
txtItem.setText(item);
txtNumber.setText(number);
txtCost.setText(cost);
txtAmount.setText(amnt);
}
}
else if (records.get(recordCount) == null)
{
JOptionPane.showMessa
Check the size of arrayList before calling get() like,
if(recordCount< records.size() && records.get(recordCount) != null)
{
//Do the processing
} else {
JOptionPane.showMessa
}

How to prevent my program from crashing due to a user's input

I am trying to implement an algorithm "recongnizng strings in a language "
L = {'w$w' : w is a possible empty string of characters other than $,
w' = reverse(w)}
my problem is whenever i input anything without having $, it crashes on the while loop. what will be the best way to prevent it from crashing?
public boolean isInLanguage(String inputString)
{
StackReferenceBased stack1 = new StackReferenceBased();
StackReferenceBased stack2 = new StackReferenceBased();
Object qItem;
Object sItem;
int index = 0;
if (inputString.length() == 0)
{
return false; // empty string not in L
}
else if (inputString.length() == 1)
{
return true;
}
**while (inputString.charAt(index) != '$')**
{
// save the first half of the string
stack1.push(inputString.charAt(index));
++index;
}
// index points to '$' or its value > than inputString.length()
while (index < inputString.length()-1)
{
// save the second half of the string
++index;
stack2.push(inputString.charAt(index));
}
do
{
// match the first half of the string with the second half
if ((stack1.isEmpty() && !stack2.isEmpty()) ||(!stack1.isEmpty() && stack2.isEmpty()))
{
return false;
}
qItem = stack1.peek();
sItem = stack2.peek();
if (qItem != sItem)
{
return false;
}
if (!stack1.isEmpty())
{
stack1.pop();
}
if (!stack2.isEmpty())
{
stack2.pop();
}
}while (!stack1.isEmpty() || !stack2.isEmpty());
if (stack1.isEmpty() && stack2.isEmpty())
{
return true;
}
else
{
return false;
}
}
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 4 at java.lang.String.charAt(Unknown
Source) at
assignmnet5.StackReferenceBased.isInLanguage(StackReferenceBased.java:87)
at assignmnet5.Question3.main(Question3.java:19)
this is my main:
public static void main(String[]args)
{
StackReferenceBased stack = new StackReferenceBased();
String str;
boolean bool;
Scanner kb = new Scanner(System.in);
System.out.println( "Enter a string to be checked by the algorithm : ");
str = kb.next();
**bool = stack.isInLanguage(str);**
if (bool == true)
System.out.println( "The string is in language");
else
System.out.println("The string is not in language");
}
It sounds like this might suffice:
if (inputString == null || !inputString.contains("$")) {
return false; // empty string not in L
}
possible issue is a null pointer exception, try to add this line in the top of your function
public boolean isInLanguage(String inputString)
{
if(inputString == null){
return false;
}
...
...
complete your code
if you still have crashes, you will need to provide the error you've got when you run the code.

StackOverFlowError in Java postfix calculator

The following class is used by another program. When it is accessed, it throws a StackOverFlowError. This is part of a Postfix Calculator I have to do as a project at my university.
Any help would be greatly appreciated, thank you in advance. I'm quite new at Java and I have no idea what to do.
CODE:
import java.util.Queue;
import java.util.Stack;
public class MyPostfixMachine implements PostfixMachineInterface {
MyMathOperations mmo = new MyMathOperations();
MyPostfixMachine mpm = new MyPostfixMachine();
public String evaluate(Queue q) {
if (q.isEmpty()) {//if the input is empty, terminate the program
System.exit(0);
}
if (q.size() == 1) {//if there is only one number in the queue, return it as the solution
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {
return String.valueOf(q.remove());
}
}
Stack<String> finalxp = new Stack<String>();//create an empty stack
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {//if first element of queue q is a number,push it into the stack
finalxp.push(String.valueOf(q.remove()));
} else {//depending on the operator perform the corresponding operations
if (q.remove() == "+") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.addition(str, str2));
}
if (q.remove() == "-") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.substraction(str, str2));
}
if (q.remove() == "*") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.product(str, str2));
}
if (q.remove() == "/") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.division(str, str2));
}
if (q.remove() == "fibo") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.fibonacci(str));
}
if (q.remove() == "fac") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.factorial(str));
}
if (q.remove() == "han") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.hanoi(str));
}
}
return String.valueOf(finalxp.pop());
}
public boolean isParsableToDouble(String candidate) {
try {
Double.parseDouble(candidate);
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
}
public class MyMathOperations implements MathOperationsInterface {
public String addition(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A + B));
}
public String substraction(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A - B));
}
public String product(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A * B));
}
public String division(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A / B));
}
public String fibonacci(String s) {
int n = Integer.parseInt(s);
return String.valueOf(fibo(n));
}
public int fibo(int f) {
if (f < 0) {
throw new IllegalArgumentException("Cannot apply Fibonacci method");
} else if (f == 0) {
return 0;
} else if (f == 1) {
return 1;
} else {
return fibo(f - 1) + fibo(f - 2);
}
}
public String hanoi(String s) {
int a = Integer.parseInt(s);
int han = 0;
if (a < 0) {
throw new IllegalArgumentException("Not a valid integer");
} else {
han = (int) Math.pow(2, a) - 1;
}
return String.valueOf(han);
}
public String factorial(String s) {
int a = Integer.parseInt(s);
if (a < 0) {
throw new IllegalArgumentException("Incorrect argument for factorial operatiion");
}
switch (a) {
case 0:
case 1:
return String.valueOf(1);
default:
int res = a;
while (true) {
if (a == 1) {
break;
}
res *= --a;
}
return String.valueOf(res);
}
}
private static double pDouble(String s) {
double res = 0d;
try {
res = Double.parseDouble(s);
} catch (NumberFormatException e) {
System.exit(1);
}
return res;
}
}
The problem is that your class MyPostfixMachine has a private field MyPostfixMachine mpm which is initialized with a new MyPostfixMachine. Since this new MyPostfixMachine also has a private field MyPostfixMachine mpm which is initialized with a new MyPostfixMachine... you get it. :) This goes on and on forever (or until your stack is full).
Here is the problematic piece of code:
public class MyPostfixMachine implements PostfixMachineInterface {
MyMathOperations mmo = new MyMathOperations();
MyPostfixMachine mpm = new MyPostfixMachine(); // problem is here
// ...
}
I think you can simply remove the private field mpm. Just call the methods on the current instance. So instead of:
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {...}
you can simply write:
if (isParsableToDouble(String.valueOf(q.remove()))) {...}
or (equivallent but more explicit):
if (this.isParsableToDouble(String.valueOf(q.remove()))) {...}
Anyway, just remove the private field mpm and the StackOverflowException should be gone.
I'm not sure how you're getting a StackOverflowError (I don't see any loops or recursion in this code), but one definite problem is your overuse of Queue.remove(). Every time you look at the queue in your if clauses, you're lopping-off the first element -- I'd expect this code to be barfing-out NoSuchElementExceptions.
To say nothing of all the EmptyStackExceptions you should be getting from popping from an empty Stack.
So I'd say....
Quit calling `remove()` when you should be calling `peek()` instead.
Quit popping from an empty stack; you want to be pulling those values from your input queue, yes?
The problem giving you your `StackOverFlowError` is elsewhere. (Unless I'm overlooking something -- always possible!) Look for a loop or a recursive call.

Categories

Resources