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

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

Related

hbase: assign CompareFilter.CompareOp based on input value

Can we take the compareOperator value based on input value? For example if my input is eq, then it should pick CompareFilter.CompareOp.EQUAL, else if input is ne it should pick CompareFilter.CompareOp.NOT_EQUAL.
Something like
if(input.equals("eq")) {
myCompareOp = EQUAL;
}else if(input.equals("ne")) {
myCompareOp = NOT_EQUAL;
}
SingleColumnValueFilter colValFilter = new SingleColumnValueFilter(Bytes.toBytes(<CF>), Bytes.toBytes(<CQ>)
, myCompareOp, new BinaryComparator(Bytes.toBytes(<value>)));
Any suggestions will be appreciated
Based on above code , Yes it will work. Below is the example code snippet, you can have a look as well.where ConditionType is enum... like this you can also prepare your own enum(not mandatory if condition is also fine)
private Filter buildSimpleQuery(ConditionType ct, String name, Object value) {
name = super.getRealPropertyName(name);
validatePropertyValue(name, value);
Class<?> clazz = getPrimitiveFieldClass(name, value.getClass());
CompareOp compareOp = null;
boolean regexCompRequired = false;
switch (ct) {
case EQUALS:
compareOp = CompareOp.EQUAL;
regexCompRequired = String.class == clazz && value.toString().endsWith("*");
break;
case NOT_EQUALS:
compareOp = CompareOp.NOT_EQUAL;
regexCompRequired = String.class == clazz && value.toString().endsWith("*");
break;
case GREATER_THAN:
compareOp = CompareOp.GREATER;
break;
case GREATER_OR_EQUALS:
compareOp = CompareOp.GREATER_OR_EQUAL;
break;
case LESS_THAN:
compareOp = CompareOp.LESS;
break;
case LESS_OR_EQUALS:
compareOp = CompareOp.LESS_OR_EQUAL;
break;
default:
break;
}
String qualifier = name;
String theFamily = family != null ? family : familyMap.get(qualifier);
ByteArrayComparable byteArrayComparable = regexCompRequired
? new RegexStringComparator(value.toString().replace("*", "."))
: new BinaryComparator(value.toString().getBytes(StandardCharsets.UTF_8));
Filter query = new SingleColumnValueFilter(theFamily.getBytes(StandardCharsets.UTF_8),
qualifier.getBytes(StandardCharsets.UTF_8),
compareOp,
byteArrayComparable);
return query;
}

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

use relational operators in switch

Is there a way to use relational operators (<,<=,>,>=) in a switch statement?
int score = 95;
switch(score) {
case (score >= 90):
// do stuff
}
the above example (obviously) doesn't work
No you can not.
From jls-14.11
The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs.
Relational operators (<,<=,>,>=) results in boolean and which is not allowded.
All of the following must be true, or a compile-time error occurs:
Every case constant expression associated with a switch statement must be assignable (§5.2) to the type of the switch Expression.
No two of the case constant expressions associated with a switch statement may have the same value.
No switch label is null.
At most one default label may be associated with the same switch statement.
This might help you if you need to do it with switch itself,
char g ='X';
int marks = 65;
switch(marks/10)
{
case 1:
case 2:
case 3:
case 4: g = 'F';
break;
case 5: g = 'E';
break;
case 6: g = 'D';
break;
case 7: g = 'C';
break;
case 8: g = 'B';
break;
case 9:
case 10: g = 'A';
break;
}
System.out.println(g);
It works this way,
if(marks<50)
g='F';
else if(marks<60)
g='E';
else if(marks<70)
g='D';
else if(marks<80)
g='C';
else if(marks<90)
g='B';
else if(marks<=100)
g='A';
Unfortunately NO, though you can use case fall (kind of hacky) by grouping multiple case statements without break and implement code when a range ends:
int score = 95;
switch(score) {
..
case 79: System.out.println("value in 70-79 range"); break;
case 80:
..
case 85: System.out.println("value in 80-85 range"); break;
case 90:
case 91:
case 92:
case 93:
case 94:
case 95: System.out.println("value in 90-95 range"); break;
default: break;
}
IMHO, using if would be more appropriate in your particular case.
It will never work. You should understand what switch does in the first place.
It will execute the statements falling under the case which matches the switch argument.
In this case, score is an argument which is 95 but score>=90 will always evaluate to either true or false and never matches an integer.
You should use if statements instead.
Also Java doesn't allow booleans in switch cases so yea.
Simply NO
int score = 95;
switch(score) {
case (score >= 90):
// do stuff
}
You are passing a int value to switch. So the case's must be in int values, where
(score >= 90)
Turns boolean.
Your case is a good candidaate for if else
The docs for switch-case statement state:
a switch statement tests expressions based only on a single integer, enumerated value, or String object.
So there is no boolean. Doing so would make no sence since you only have two values: true or false.
What you could do is write a method which checks the score and then returns a one of the types switch can handle
For example:
enum CheckScore {
SCORE_HIGHER_EQUAL_90,
...
}
public CheckScore checkScore(int score) {
if(score >= 90) {
return SCORE_HIGHER_EQUAL_90;
} else if(...) {
return ...
}
}
and then use it in your switch:
switch(checkScore(score)) {
case SCORE_HIGHER_EQUAL_90:
// do stuff
}
... Or You could just use if, else-if, else directly!
Obviously, this is not possible as a language construct. But, just for fun, we could implement it by ourselves!
public class Switch<T, V> {
public static interface Action<V> {
V run();
}
private final T value;
private boolean runAction = false;
private boolean completed = false;
private Action<V> actionToRun;
public Switch(T value) {
this.value = value;
}
static public <T, V> Switch<T, V> on(T value) {
return new Switch<T, V>(value);
}
public Switch<T, V> ifTrue(boolean condition) {
runAction |= condition;
return this;
}
public Switch<T, V> ifEquals(T other) {
return ifTrue(value.equals(other));
}
public Switch<T, V> byDefault(Action<V> action) {
this.actionToRun = action;
return this;
}
public Switch<T, V> then(Action<V> action) {
if (runAction && !completed) {
actionToRun = action;
completed = true;
}
return this;
}
public V getResult() {
if (actionToRun == null) {
throw new IllegalStateException("none of conditions matched and no default action was provided");
}
return actionToRun.run();
}
}
Switch accepts any value to switch on and then provides functionality to match over boolean conditions (ifTrue method) or by exact matches (ifEquals method). Providing a value to switch on is needed just for the latter feature.
After building the conditions, user invokes getResult to obtain the result.
For example, we could create a method that tells us what it thinks about our score:
String tellMeMyScore(int score) {
return Switch.<Integer, String> on(score).byDefault(new Action<String>() {
public String run() {
return "really poor score";
}
}).ifTrue(score > 95).then(new Action<String>() {
public String run() {
return "you rock!";
}
}).ifTrue(score > 65).then(new Action<String>() {
public String run() {
return "not bad, not bad";
}
}).ifEquals(42).then(new Action<String>() {
public String run() {
return "that's the answer!";
}
}).getResult();
}
This simple test:
for (int score : new int[] { 97, 85, 66, 55, 42, 32, 4 }) {
System.out.println(score + ": " + tellMeMyScore(score));
}
Prints out:
97: you rock!
85: not bad, not bad
66: not bad, not bad
55: really poor score
42: that's the answer!
32: really poor score
4: really poor score

how to refactor the following codes

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.

switch / case request with boolean

I'm trying to create a method which checks if the Login (username and password) has a minimum of 6 charakters.
To realize that I created this method public void checkLoginData(final String username, final String password). In that method, I create to booleans (user and pass), with those I can create 4 different boolean-chains:
user: true pass: true
user: false pass: true
user: false pass: false
user: true pass: false
Now I'd like to do a switch/case request for each of them, but I don't get how to realize that...
If you ask why I need the switch, I just think I need it, because I'd like to do for every of those 4 boolean-chains, that it does/show something diffrent. Also I'd like to do this in a sexy-java-way not with tousands of diffrent 'ifs' :P, Please help!
Here's the code of the method:
public void checkLoginData(final String username, final String password){
boolean user, pass;
if (username.length() < 6){
user = false;
}else {
user = true;
}
if (password.length() < 6){
pass = false;
}else {
pass = true;
}
boolean[] logindaten = {user, pass};
}
Thx for the help in Advance!
Best Regards safari
If you really want a "sexy-java-way" (but that depends what you understand as such) you can do something like (Java 7 required):
boolean user, pass;
switch (user + "-" + pass) {
case "false-false":
...
case "false-true":
...
case "true-false":
...
case "true-true":
...
default:
throw new RuntimeException(
"something strange happening here, user: " + user + ",pass: " + pass);
}
but I would prefer to do just 2 distinct checks each with his owns message, the message being joined for presentation. (and not sure if that could be considered "sexy-java-way", more like a 'workaround')
You can't switch over boolean[], only over integral types. To convert the booleans to an int, you could use a bit mask for the 2 booleans, like for example this:
int val = 0;
if (user) val |= 0x1;
if (pass) val |= 0x2;
switch (val) {
case 0: // Both too short
case 1: // User Ok, pass too short
case 2: // User too short, pass ok
case 3: // Both Ok
}
Guess thats how I would solve it with enums:
public class LoginController
{
private void login( String username, String password )
{
LoginState state = determineLoginState( username, password );
switch ( state )
{
case LOGIN_OK:
//Do Something
break;
case USERNAME_FALSE:
//Do Something
break;
case PASSWORD_FALSE:
//Do Something
break;
case BOTH_FALSE:
//Do Something
break;
}
}
private LoginState determineLoginState( String username, String password )
{
final boolean checkUsername = checkUsername( username );
final boolean checkPassword = checkPassword( password );
if ( checkUsername && checkPassword )
return LoginState.LOGIN_OK;
if ( !checkUsername && checkPassword )
return LoginState.USERNAME_FALSE;
if ( checkUsername && !checkPassword )
return LoginState.PASSWORD_FALSE;
if ( !checkUsername && !checkPassword )
return LoginState.BOTH_FALSE;
throw new AuthenticationException();
}
protected boolean checkUsername( String username )
{
return username.length() > 6;
}
protected boolean checkPassword( String password )
{
return password.length() > 6;
}
private enum LoginState
{
LOGIN_OK, USERNAME_FALSE, PASSWORD_FALSE, BOTH_FALSE;
}
public class AuthenticationException extends RuntimeException
{
}
}
Basically there is no simpler way than this, and no way to do it in significantly less lines of code.
if (username.length() < 6){
if (password.length() < 6){
// do case 1
} else {
// do case 2
}
} else {
if (password.length() < 6){
// do case 3
} else {
// do case 4
}
}
To my mind, that makes this the best solution.
Also I'd like to do this in a sexy-java-way not with tousands of diffrent 'ifs'
If by "sexy-java-way" you mean "clever" or "obscure", then there are other ways to do it. But they certainly don't make the code easier to read / more maintainable.
By the way, the above involves only 3 ... that's right THREE ... if statements.
However your (final) specific example:
public void checkLoginData(final String username, final String password){
boolean user, pass;
if (username.length() < 6){
user = false;
}else {
user = true;
}
if (password.length() < 6){
pass = false;
}else {
pass = true;
}
boolean[] logindaten = {user, pass};
....
}
can be simplified to the following:
public void checkLoginData(final String username, final String password){
boolean user = username.length() >= 6;
boolean pass = password.length() >= 6;
boolean[] logindaten = {user, pass};
....
}
Note that simplification is possible here because the actions (the "cases" in your hypothetical switch) can be refactored into simple boolean assignments AND the tests are actually independent of each other. In general you can't do that ...
... but id like to have it more celver to impress my boss ;)
Seriously, if I was your boss and you wrote code like that, I'd be UN- impressed. Any boss who thinks you are clever for writing obscure and unmaintainable code is clueless.
if (user) {
if (pass) {
// user = true, pass = true
} else {
// user = true, pass = false
}
} else {
if (pass) {
// user = false, pass = true
} else {
// user = false, pass = false
}
}
Or
int case = user ? (pass ? 1 : 2) : (pass ? 3: 4);
switch (case) {
case 1:
System.out.println(" user = true, pass = true ");
break;
case 2:
System.out.println(" user = true, pass = false ");
break;
case 3:
System.out.println(" user = false, pass = true ");
break;
case 4:
System.out.println(" user = false, pass = false ");
break;
}
}
You can do something like this and then each case is 1,2 or 3, etc.
switch((route.isComplete()?1:(route.getAuthentic()?2:(route.hasRoute()?3:0)))) {...}
With java12, you can use expressions within switch-case and provide a Bool type (https://blog.codefx.org/java/switch-expressions/).
private static boolean checkCharOf_(String userName){
return userName.length() >= 6;
}
private static boolean checkCharOf_(String password){
return password.length() >= 6;
}
or
private static boolean checkCharOf_And_(String userName, String password){
return userName.length() >= 6 && password.length() >= 6;
}

Categories