how to refactor the following codes - java

I have a method want to refactor, and some dummy codes as below:
if(deletedInfo.isEmpty() && addedInfo.isEmpty()) {
// some logic codes
} else if (!deletedInfo.isEmpty() && addedInfo.isEmpty()) {
// some logic codes
} else if (deletedInfo.isEmpty() && !addedInfo.isEmpty()) {
// some logic codes
} else if(!deletedInfo.isEmpty() && !addedInfo.isEmpty()) {
// some logic codes
}
is there a appropriate pattern or some algorithm to refactor this codes?
Thanks.

if (deletedInfo.isEmpty()) {
if (addedInfo.isEmpty()) {
// some logic codes
} else {
// some logic codes
}
} else {
if (addedInfo.isEmpty()) {
// some logic codes
} else {
// some logic codes
}
}

You can refactor with this code:
int val = 0;
if (deletedInfo.isEmpty()) val |= 0x1;
if (addedInfo.isEmpty()) val |= 0x2;
switch (val) {
case 0: // some logic codes
case 1: // some logic codes
case 2: // some logic codes
case 3: // some logic codes
}

There are a couple of ways you could do it. Here's one:
if (a) {
if (b) {
// do J
} else {
// do K
}
} else {
if (b) {
// do L
} else {
// do M
}
}
You might prefer something more akin to a truth table, particularly if you have more than two tests to combine:
int switcher = 0;
if (a) switcher|=1;
if (b) switcher|=2;
switch(switcher) {
case 0:
// do J
break;
case 1:
// do K
break;
case 2:
// do L
break;
case 3:
// do M
break;
}
I don't think there is an automatically "right" way - you have to choose whatever is clearest for your situation.

Related

How to change this code from switch case to if else?

How to use if-else to write this code?
I'd like to know the difference between the two methods. Thanks
switch (status) {
case AIRCRAFT_CARRIER_HIT:
if (this.getFleet().updateFleet(ShipType.ST_AIRCRAFT_CARRIER))
result[1] = "a";
break;
case BATTLESHIP_HIT:
if (this.getFleet().updateFleet(ShipType.ST_BATTLESHIP))
result[1] = "a";
break;
case CRUISER_HIT:
if (this.getFleet().updateFleet(ShipType.ST_CRUISER))
result[1] = "a";
break;
case DESTROYER_HIT:
if (this.getFleet().updateFleet(ShipType.ST_DESTROYER))
result[1] = "a";
break;
case SUB_HIT:
if (this.getFleet().updateFleet(ShipType.ST_SUB))
result[1] = "a";
break;
default:
result[1] = null;
In an if statement, the enum has to be in full form and the variable compared to has to be mentioned in all the conditions. I don't know the name of the enum, but I'll guess it's Status. In that case you'd write
if (status == Status.AIRCRAFT_CARRIER_HIT) {
if (this.getFleet().updateFleet(ShipType.ST_AIRCRAFT_CARRIER)) {
result[1] = "a";
}
} else if (status == Status.BATTLESHIP_HIT) {
// etc.
} else {
result[1] = null;
}
your switch statement can be written as below with if/else (assuming the variables AIRCRAFT_CARRIER_HIT etc are final and assigned a value at compile time, eg final int AIRCRAFT_CARRIER_HIT = 3 :
if (status == AIRCRAFT_CARRIER_HIT ) {
...
}
else if (status == BATTLESHIP_HIT) {
...
}
…
…
else {
// default case
}
for differences and pros/cons of each approach you can check here for example

Repeat something until it succeeds, but at most 3 times

I have needed to program something like this several times since programming Java:
Do something that might fail. If it fails, try it again but at most 3 (or 2 or 5) times.
This approach should work:
for (int i = 0; i < 3; i++) {
try {
doSomething();
} catch(BadException e) {
continue;
}
break;
}
But I do not think that it is very expressive. Do you have a better solution?
Something like this would be nice:
try (maxTimes = 3) {
doSomething();
} catch(BadException e) {
retry;
}
Or:
try (maxTimes = 3) {
doSomething();
if(somethingFailed()) {
retry;
}
}
But this is not possible with Java. Do you know a language with which it is possible?
Java does not let you invent your own syntax, but you can define your own method to help you express the concept with less code:
public static boolean retry(int maxTries, Runnable r) {
int tries = 0;
while (tries != maxTries) {
try {
r.run();
return true;
} catch (Exception e) {
tries++;
}
}
return false;
}
Now you can call this method like this:
boolean success = retry(5, () -> doSomething());
// Check success to see if the action succeeded
// If you do not care if the action is successful or not,
// ignore the returned value:
retry(5, () -> doSomethingElse());
Demo.

Java: Using created string as loop parameter?

In short, the user will input a number (say 1 through 3). This will decide which range of numbers the loop should search through.
switch(input){
case 1:
searchTerm = "i<10 && i>5";
case 2:
searchTerm = "i>=10 && i<19";
case 3:
searchTerm = "i>19 && i<24";
}
while(searchTerm){
//some function
}
Is this possible? I I've not been able to find a way to use a string as search parameters.
EDIT: I don't think I did a very good job of explaining why I needed this. What is one to do if there are different numbers of parameters? For example:
case 1:
searchTerm = "i<5"
case 2:
searchTerm = "i>25 && i<29"
case 3:
searchTerm = "(i<50 && i>25) && (i>55 && i<75)"
case 4:
searchTerm = "(i<20 && i>15) && (i>300 && i<325) && (i>360 && i<380)
Then how does one do it? Multiple loops that call the same function?
The correct way to do this is to not use a string at all:
int min, max;
switch(input){
case 1: // i<10 && i>5
min = 6;
max = 10;
break; // to avoid follow-through to the next case
case 2: // i>=10 && i<19
min = 10;
max = 20;
break;
case 3: // i>19 && i<24
min = 20;
max = 25;
break;
default:
// You need something here in case the value entered wasn't 1-3
}
for (int i = min; i < max; ++i) {
// ...
}
Re your edit:
I don't think I did a very good job of explaining why I needed this. What is one to do if there are different numbers of parameters?
In that case, you'll have to use an expression evaluator (or write one, which is a non-trivial task). There's one in Spring, for instance (not recommending, just happened to hear about it). A search for "Java expression evaluator" should turn up some options.
Another alternative, which is somewhat amusing given that some folks mistook your question for a JavaScript question, is to use the JavaScript evaluator built into Java (either Rhino or Nashorn). E.g.: Live Example
import javax.script.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
String searchTerm = "i >= 19 && i <= 24";
int i;
try {
i = 19;
engine.put("i", i);
while ((boolean)engine.eval(searchTerm)) {
System.out.println("i = " + i);
++i;
engine.put("i", i);
}
System.out.println("Done");
} catch (ScriptException scriptException) {
System.out.println("Failed with script error");
}
}
}
...but you'll still have the problem of determining what initial value to use for i, which I've hardcoded above.
In Java 8 you can select a lambda instead of String:
Predicate<Integer> searchTerm = (Integer v) -> false;
switch (input) {
case 1:
searchTerm = (Integer v) -> v < 10 && v > 5;
break;
case 2:
searchTerm = (Integer v) -> v >= 10 && v < 19;
break;
case 3:
searchTerm = (Integer v) -> v > 19 && v < 24;
break;
}
while (searchTerm.test(i)) {
...
}
You can create an enumeration as below.
public enum SearchTerms {
None(""),
Between6And9("i<10 && i>5"),
Between10And18("i>=10 && i<19"),
Between20And23("i>19 && i<24");
private final String stringValue;
SearchTerms(String stringValue) {
this.stringValue = stringValue;
}
public String getStringValue() {
return stringValue;
}
public static SearchTerms fromStringValue(String stringValue) {
for (SearchTerms searchTerm : values()) {
if (searchTerm.getStringValue().equalsIgnoreCase(stringValue)) {
return searchTerm;
}
}
return SearchTerms.None;
}
}
Usage:
SearchTerms searchTerm = SearchTerms.fromStringValue("i<10 && i>5");
switch(searchTerm) {
case Between6And9:
//dosomething
break;
}
You can use .eval() of JavaScript.
Also don't forget break; at the end of each case:
Check out this fiddle.
Here is the snippet.
function test(input, i) {
switch (input) { //input=1
case 1:
searchTerm = "i<10 && i>5"; //this will be 'searchTerm'
break;
case 2:
searchTerm = "i>=10 && i<19";
break;
case 3:
searchTerm = "i>19 && i<24";
break;
}
while (eval(searchTerm)) { //'searchTerm' converted to boolean expression
alert(i); // alert for i=7,8,9
i++;
}
}
test(1, 7); //pass input=1 and i=7

how to jump from inner loop to outer loop

Here is the structure of my program:
for(loop1){
if(condition1)
{
for(loop2)
{
for(loop3)
{
if(condition1_3)
{
As condition1_3 is true continue with loop2's next iteration,
No need to execute loop3's remaining iteration
}
else
{
As condition1_3 is false no need to execute remaining part of loop3 and
loop 2 but continue with loop1's remaining part i.e. condition1_1
}
}
}
}
if(condition1_1)
{
some code here
}
}
I know I have to use continue and break statement but don't understand exactly how?
Please tell me how to achieve this mechanism?
If I understand your question, you could use the labeled continue,
loop1: for (;;) {
if (condition1) {
loop2: for (;;) {
loop3: for (;;) {
if (condition1_3) {
continue loop2;
} else {
continue loop1;
}
}
}
}
}
You can do as follows:
for(loop1){
if(condition1)
{
for(loop2)
{
boolean flag=false;
for(loop3)
{
if(condition1_3)
{
break;
}
else
{
flag=true;
break;
}
}
if(flag)
break;
}
}
if(condition1_1)
{
some code here
}
}
Do like the following -
for(loop1){
boolean flag = false;
if(condition1)
{
for(loop2)
{
if(flag == true)
break;
for(loop3)
{
if(condition1_3)
{
break;
}
else
{
flag = true;
break;
}
}
}
}
if(condition1_1)
{
some code here
}
}
An option would be to use variables - but you have to think about correct setting of values:
boolean runFor1 = true;
boolean runFor2 = true;
boolean runFor3 = true;
for(loop1 && runFor1)
{
for(loop2 && runFor2)
{
for(loop3 && runFor3)
{
setRunForX here to skip/unskip loops
}
}
}
}
Have a exit flags which is set when you want to exit a particular loop and check in each respective loops whether to continue or exit.
boolean exitLoop2 = false;
for(loop1){
if(condition1)
{
for(loop2)
{
for(loop3)
{
if(condition1_3)
{
//As condition1_3 is true continue with loop2's next iteration,
//No need to execute loop3's remaining iteration
break;
}
else
{
//As condition1_3 is false no need to execute remaining part of loop3 and
//loop 2 but continue with loop1's remaining part i.e. condition1_1
exitLoop2 = true;
break;
}
}
if(exitLoop2)
{
break;
}
}
}
if(condition1_1)
{
some code here
}
}
To break out and not continue the loop3 use break; if (condition1_3) break; The break; statement only breaks out of the current loop i think, not the loop it is nested in.
Edit: Missread the question
To break out of both loops you can make a boolean flag before both loops and at the end of both loops have an if (breakOut) break; This will solv the question
I'm not really shure what do you mean exactly. For me it simply looks like you want to jump out of the loops if a specific condition is satisfied. So you can either can define a label for your loops and use the continue labelLoopX; statement or you can satisfy the exit condition of loop3 if condition1_3==true resp. the exit condition of loop3 and loop2 if condition1_3==false. e.g. if loop3 looks like for ( int i = 0; i < 10; i++ ) like this:
if(condition1_3){
//do something important
i=10; //sets i to 10 and condition i < 10 is unsatified
}
else{
//do some other important stuff
i=10; //satify loop3's exitcondition
j=10; //satify loop2's exitcondition
}

Is this considered code duplication?

If I want to test multiple values of an enum using a case statement, and 80% of the case statements require two different if checks, is it considered poor coding to reuse that code over and over?
I actually used ctrl+c and ctrl+v and felt like the code gods would kill me.
Here is some perspective:
switch(value) {
case value1:
{
if(something) { //do something; }
if(somethingElse) { // do something else; }
//unique for value1
}
break;
case value2:
{
//unique for value2
}
break;
case value3:
{
if(something) { //do something; }
if(somethingElse) { // do something else; }
//unique for value3
}
break;
case value4:
{
if(something) { //do something; }
if(somethingElse) { // do something else; }
//unique for value4
}
break;
case value5:
{
//unique for value5
}
break;
default:
break;
My value is randomly generated from the enum and is called a random amount of times. The goal is for value to be any random 'value' and totally independent of other cases.
You might want to put this duplicate code into a method.
public void yourFunctionCall() {
//Could even pass the value if needed
if(something) { //do something; }
if(somethingElse) { // do something else; }
}
Then call this method in your case:
switch(value) {
case value1: {
yourFunctionCall();
//or yourFunctionCall(value1);
//unique for value1
} //etc..
If this a reusable piece of code, you're better off turning it into a method. If not, you could simply add another switch case covering the common code using fall-through as:
switch (value) {
case value1:
case value3: // using fall-through
case value4:
{
if (something) { /* do something; */ }
if (somethingElse) { /* do something else; */ }
}
}
switch (value) {
case value1:
{
// unique for value1
break;
}
case value2:
{
// unique for value2
break;
}
// other unique cases
}
Using a function is probably better, but here's another way:
case value1:
case value3:
case value4:
if(something) { /* do something */ }
if(somethingElse) { /* do something else */ }
if (value1)
{
//unique for value1
}
else if (value3)
{
//unique for value3
}
else // if (value4)
{
//unique for value4
}
break;
case value2:
...
Or with nested switch:
case value1:
case value3:
case value4:
if(something) { /* do something */ }
if(somethingElse) { /* do something else */ }
switch(value)
{
case value1: /* unique for value1 */ break;
case value3: /* unique for value3 */ break;
case value4: /* unique for value4 */ break;
}
break;
case value2:
...
Use with care, I wouldn't really recommend either for production code.

Categories