Ive got a while loop that keeps running as long as an if is true at least once per loop but i cant find the reason why the loop wont stop. (there are a couple more ifs but i removed them because they are the exact same)
boolean changed = true;
do{
boolean stopLoop = false;
if(remove1=="")
{
EquipmentSlot1.setText(EquipmentSlot2.getText());
EquipmentSlot2.setText("");
stopLoop = true;
}
if(remove2=="")
{
EquipmentSlot2.setText(EquipmentSlot3.getText());
EquipmentSlot3.setText("");
stopLoop = true;
}
if(remove3=="")
{
EquipmentSlot3.setText(EquipmentSlot4.getText());
EquipmentSlot4.setText("");
stopLoop = true;
}
if(stopLoop = false)
{
changed = false;
}
}while(changed);
Change
if (stopLoop = false)
to
if (stopLoop == false)
Note that = is for assignment, == for comparison.
Or better yet (and recommended):
if (!stop)
Edit:
Also, to compare Strings, use equals() method:
if (remove1.equals(""))
...
First, your last if is an assignment, not a test of equality, i.e. stopLoop = false should be == false
Second, changed has no way to be false in any if you have shown.
Related
I'm making some changes into an old code than requires maintenance, and I found something like this
public boolean aMethod(){
boolean isValid = true;
**isValid = isValid &&** executeGetDocs(id.toString(),program().toString(), document.get(name));
return isValid;
}
The method executeGetDocs may return true or false.
But I'm not sure if: **isValid = isValid && executeGetDocs ** is correct or is just redundant.
So here I am, can anyone please, give me some explanation about this?
Thanks a lot!
EDITED
Whole method:
private boolean validateDocs(List<Map<String, Object>> documentsList) {
boolean isValid = true;
StringBuilder gradoAntComp = new StringBuilder();
for (Map<String, Object> document : documentsList) {
String id = document.get("ID_DOC").toString();
if (id.equalsIgnoreCase("25")) {
isValid = getData(id.toString(),program().toString(), document.get(name))
} else if (id.equalsIgnoreCase("26") ) {
isValid = isValid && getDocs(id.toString(),program().toString(), document.get(name));
}
}
return isValid;
}
Not that we see your entire method, we can see that you're attempting to assign to isValid within a loop. Written this way, the code is using the && conditional-and operator to only execute the method getDocs if isValid is still true.
If a previous assignment to isValid set it to false, then getDocs won't even be called; it will be short-circuited. This means that the && operator already knows that the result of the expression will be false, because isValid is false, so it "short-circuits" the evaluation and doesn't evaluate the other operand -- the call to getDocs.
This makes a lot of sense especially if getDocs is a method with a large overhead cost.
It was redundant in your original question. The original method you posted could be reduced to:
public boolean aMethod() {
return executeGetDocs(id.toString(),program().toString(), document.get(name));
}
since (true && x) == x for any boolean x.
However, since you changed the question, the answer changes as well. Now the boolean variable may change multiple times within a loop. Therefore it makes sense to AND the previous value of the variable (which may be true or false) with another boolean, which might cause its value to change.
private boolean validateDocs(List<Map<String, Object>> documentsList) {
boolean isValid = true;
StringBuilder gradoAntComp = new StringBuilder();
for (Map<String, Object> document : documentsList) {
String id = document.get("ID_DOC").toString();
if (id.equalsIgnoreCase("25")) {
// this can set isValid to either false or true
isValid = getData(id.toString(),program().toString(), document.get(name))
} else if (id.equalsIgnoreCase("26") ) {
// therefore performing logical AND between the previous value of
// isValid and some additional boolean is meaningful - isValid will
// be assigned true only if it was true before this statement AND
// getDocs(id.toString(),program().toString(), document.get(name)) is true
isValid = isValid && getDocs(id.toString(),program().toString(), document.get(name));
}
}
return isValid;
}
As you initialize isValid as true it's useless you can rewrite it as:
public boolean aMethod(){
return executeGetDocs(id.toString(),program().toString(), document.get(name));
}
What I am trying to perform: I am trying to reduce the conditional operators, Since Sonar is giving a error for it
if (!parseBooleanFromString(response.getBuy().getHasEligibleAccounts()) &&
(!parseBooleanFromString(response.getSell().getHasEligibleAccounts()) &&
(!parseBooleanFromString(response.getExchange().getHasEligibleAccounts()) &&
(!parseBooleanFromString(response.getWorkplaceRetirement().getHasPlansEligibleForChangeContributions()) &&
(!parseBooleanFromString(response.getWorkplaceRetirement().getHasPlansEligibleForChangeInvestments())))))) {
//Success
} else {
//Failure
}
private boolean parseBooleanFromString(String mStr) {
return Boolean.parseBoolean(mStr);
}
What i have tried:
I am trying to put all the boolean values in a list and check
Is that the best way to do or is there a more efficient way
You can also move these conditions into different functions which internally calls other functions and returns single boolean result. This way there will only one function in above if condition which will internally evaluate and returns result.
Since you're checking if each statement is false, how about you keep a global integer in memory: private int product = 1;. Make a separate method where you calculate the product (replaces the string to boolean parser):
private void updateProduct(String mStr){
if (Boolean.parseBoolean(mStr)) //If true, condition should fail
product *= 0;
else
product *= 1;
}
In essence, you are not running 'if statement' but multiplying the boolean:
product = 1;
updateProduct(response.getBuy().getHasEligibleAccounts());
updateProduct(response.getSell().getHasEligibleAccounts());
//etc
if (product > 0){
//success
} else {
//failure
}
Explanation: If at any point a condition was true, the product will always be 0. The only instance where the product is > 0 is when all statements were false
Not sure what sonar complains about, but you have alot of redundant parenthesis and confusing negations. Using DeMorgans law, you can at least simplify to:
boolean b = parseBooleanFromString(response.getBuy().getHasEligibleAccounts())
|| parseBooleanFromString(response.getSell().getHasEligibleAccounts())
|| parseBooleanFromString(response.getExchange().getHasEligibleAccounts())
|| parseBooleanFromString(response.getWorkplaceRetirement().getHasPlansEligibleForChangeContributions())
|| parseBooleanFromString(
response.getWorkplaceRetirement().getHasPlansEligibleForChangeContributions());
if (!b) {
or if you perfer more java 8 syntax
Stream<Boolean> bools = Stream.of(parseBooleanFromString(response.getBuy().getHasEligibleAccounts()),
parseBooleanFromString(response.getSell().getHasEligibleAccounts()),
parseBooleanFromString(response.getExchange().getHasEligibleAccounts()),
parseBooleanFromString(response.getWorkplaceRetirement().getHasPlansEligibleForChangeContributions()),
parseBooleanFromString(response.getWorkplaceRetirement().getHasPlansEligibleForChangeContributions()));
boolean c = ! bools.anyMatch(e -> e);
if (!c) {
I would do something like this:
private boolean checkEligibility(LaunchPoints response) {
final String trueStr = "true";
if (trueStr.equals(response.getBuy().getHasEligibleAccounts())) return true;
if (trueStr.equals(response.getSell().getHasEligibleAccounts())) return true;
[...]
return false;
}
The idea is, skip the parsing boolean, just check for "true" and make your conditions more readable.
I am writing some java code to check multiple conditions by if-else. The code is working properly but it is hard to do unit test.
reads lines that contains keyword conditionOne, conditionTwo or other keywords. hasConditionOneEnabled and hasConditionTwoEnabled are boolean values.
My real code has more else if statements than the provide example.
Can anyone help? Or give me some hint how to make the code shorter then I can write unit test easier? Thanks
boolean a = false;
boolean b = false;
if(line.contains("conditionOne")){
if(hasConditionOneEnabled){
a = true;
}else{
b = true;
}
}else if (line.contains("conditionTwo")){
if(hasConditionTwoEnabled){
a = true;
}else{
b = true;
}
}else{
a = true;
b = true;
}
if(a && b){
// do something 1
}else if(!a && b){
// do something 2
}else if(a && !b){
// do something 3
}else{
//both false, do nothing
}
a and b cannot be both false after the set of if-else statements.
In the first two if's variable a will have the same value than the corresponding hasConditionXXEnabled and b will be set as the opposite. The default else will set both to true.
Consider the following code:
a = true;
b = true;
if(line.contains("conditionOne")){
a = hasConditionOneEnabled;
b = !a;
}
else if(line.contains("conditionTwo")){
a = hasConditionTwoEnabled;
b = !a;
}
if(a && b){
// do something 1
}
else if(b){
// do something 2
}
else{
// do something 3
}
// test it on different line String input and different int value returned...
int xxx(String line) {
if(line.contains("conditionOne")){
status = hasConditionOneEnabled?0:1;
} else if (line.contains("conditionTwo")){
status = hasConditionTwoEnabled?0:1;
} else{
status = -1;
}
return status;
}
// test it base on different status value..
switch (status) {
case 0: ...;
case 1: ...;
default: ...;
}
However, if your if-else pattern can be continuously repeat after some modification, you may just create different boolean funciton for it.
First of all both a and b can never be false, so your last else statement is redundant.
Your entire set of conditional statements can be reduced to an if - else if - else block. You don't need variables a and b since you are using them to do something else anyway. Besides vague variables names like a and b hinder readability.
Let me first show you the code and I'll walk you through it subsequently.
boolean lineContainsCond1 = line.contains("conditionOne");
boolean lineContainsCond2 = line.contains("conditionTwo");
boolean lineContainsNeitherCondition = !lineContainsCond1 && !lineContainsCond2;
boolean conditionsForSomething3 = (lineContainsCond1 && conditionOneEnabled) || (lineContainsCond2 && conditionTwoEnabled);
if(lineContainsNeitherCondition)
//do something 1 (Note: this is the same something 1 from your code)
else if(conditionsForSomething3)
//do something 3
else
//do something 2
lineContainsNeitherCondition is essentially both a and b being true in your code.
conditionsForSomething3 tantamounts to a!b.
If both lineContainsNeitherCondition and conditionsForSomething3 are false, we can derive the following conclusions:
Given lineContainsNeitherCondition is false, either lineContainsCond1 is true or lineContainsCond2 is true
Case 1 : lineContainsCond1 is true:
In this case, either conditionOneIsEnabled is true or conditionOneEnabled is false. If it were true, then conditionFOrSomething3 cannot be false, if it's false, then that leads to lineContainsCond && !conditionOneEnabled to be true which leads to b!a in the original code and thereby executes //something 2.
A similar argument can be made for Case 2 : lineContainsCond2 is true.
Why don't reduce the amount of if else statements in your code.
Try replacing the if else statements with private methods that return a boolean. Try to in cooperate the below methods or similar methods into your above code.
Having a look at mookito great for mocking and stubbing. If you have a big project with lots of Objects will save you hours maybe days.
private boolean doesLineContainCondition(String line, String searchPhrase) {
if(line.contains(searchPhrase) {
return true;
} else {
return false;
}
}
private boolean hasConditionBeenEnabled(boolean condition) {
if(condition) {
a = true;
}
else {
b= true;
}
}
Where I'm running in to problems is when a lock is already open, then pretty much an incorrect combination won't make a difference because it will remain open. This seemed easy when I read it and tried it, but the test case isn't passing. I marked the bit of code I created that isn't passing with a comment. Can someone help me figure out why it isn't working?
public void open(Combination opening){
Lock temp = new Lock(upper, opening);
if(opening.equals(unlock)){
cl = true;
}else {
//this if statement is what I came up with to find if it is open
if(temp.isOpen() == true){
cl = true;
}
cl = false;
}
}
public boolean isOpen() {
boolean op = true;
if(cl == false){
op = false;
}
return op;
}
public void close() {
cl = false;
}
There are several stylistic issues here, but I think the problem may lie with your temp Lock
if(temp.isOpen() == true){
I don't see why you need the temporary lock
public void open(Combination opening){
// If the combination is right open the lock
// if it was already open no change
if(opening.equals(unlock)){
opcl = true;
}
// no else, if combination was wrong
// leave the status as it was
}
Now as a stylistic issue the way you treat booleans is very bad. Never write
if ( bvalue == true )
just write
if ( bvlaue )
That's the whole point of booleans, they are true or false.
Hence your check is far more complex than needed, this is all you need.
// The method isOpen, which returns a
// boolean indicating whether the lock is opened or not.
public boolean isOpen() {
return opcl;
}
opcl's job is to hold the state of the lock, it's true or false, so just return that.
I get an error in the code from this part of my code:
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
}
return true;
}
When I remove the first return true and instead to the last return true, it don't get the error in my eclipse code, but why can't I have the first place and would this be the same? Thanks!
EDIT: The error message from eclipse say: This method must return a result of type boolean. I'm confused because isn't that what I have done?!
Yes, a break must be in the code
Can I write the method in some other way?
EDIT NUMBER 2
Why isn't this code working?
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
}
This method returns a boolean value so I don't understand why I get an error!? The code looks right to me?
Your edit #2 doesn't compile because there is a possibility that your code won't enter the for-loop. This will be the case if customerList.size() is 0. To fix this, you'll simply need to add a return statement after the for-loop as well:
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
return false;
Another point here is that this code doesn't logically make much sense: it will only return true or false based on the first item in your list. And this is probably not what you want. So take a closer look at several of the other answer here, many of which are good examples for how you can do this.
public boolean findCustomer(String inPersonalNumber){
boolean result = false;
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
result = true;
break;
}
}
return result ;
}
When I remove the first return true and instead to the last return
true, it don't get the error in my eclipse code, but why can't I have
the first place and would this be the same?
If you remove the second return statement the code would be able to run and not return a value - this is not possible as you defined the method to have a return type of Boolean. So it must always return a value no matter what.
Just change the second return statement to false, should do what you want.
Looks like you have turned off the Build Automatically feature of eclipse. It maybe complaining about an error that used to be present when you still hadn't typed in your code fully! This can also happen if you have back-dated your system for some reason.
Also, shouldn't you be returning false if the condition doesn't satisfy?
public boolean findCustomer(String inPersonalNumber) {
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)) {
return true;
}
}
return false;
}
First return will return only in case of all conditions satisfied, but this method should be returning boolean as per code. It would be expecting a return in failure case also.
Removing first return won't affect compilation as it has a return in second place which will work without any condtions.
Edit : Answer for your second question
This code has two return's, but what if your customerList is size 0, in that case also, method must return boolean. right? for that only, compiler is asking.
BTW, code doesn't have null checks.
Your final code could be this. Keeping multiple return statements in code in not a good practice.
public boolean findCustomer(String inPersonalNumber) {
boolean retVal = false;
if (!(inPersonalNumber == null || inPersonalNumber.trim().equals("")
|| customerList == null || customerList.size() == 0)) { // inputs are valid to run this check
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (inPersonalNumber.equals(customerList.get(i).getCustomerPersonalNumber()) { // to avoid NPE, kept inPersonalNumber in check
retVal = true;
break;
}
}
}
return retVal;
}
Because your for loop looses meaning if you're returning true anyway.
If you want to stop loop use break; instead of first return.