How to make this code simplified? I'm having doubt on having two switch statements in my function.
private String getKeyword(String id) {
String keyword = "";
switch (id.substring(1, 2)) {
case "E":
keyword = "英語";
break;
case "M":
keyword = "数学";
break;
case "W":
keyword = "統合";
break;
}
switch (id.substring(4,5)){
case "W":
keyword = "統合";
break;
}
return keyword;
}
You could use just if else if statements.
It would be less verbose.
Besides, the before last and the last condition have similarities.
So you could put them in a single statement by combining them with an OR operator. Both return "統合".
At last, you could return directly the value instead of valuing a local variable in each matched case.
But as the second switch statement overwrites the value to return,
you should move it as the first condition to test. It would make things much clearer :
private String getKeyword(String id) {
char c = id.substring(1, 2).charAt(0);
if (c == 'W' || id.substring(4,5).charAt(0) == 'W'){
return "統合";
}
else if (c == 'E'){
return "英語";
}
else if (c == 'M'){
return "数学";
}
return "";
}
private String getKeyword(String id) {
String keyword = "";
switch (id.substring(1, 2)) {
case "E":
keyword = "英語";
break;
case "M":
keyword = "数学";
break;
case "W":
keyword = "統合";
break;
}
if ("W".equals(id.substring(4, 5))) keyword = "統合";
return keyword;
}
You could use an Enumeration.
Each of them would contain one or multiple id and the corresponding keyword: easier to read and maintain.
Finally, declare a static method in the Enumeration to retrieve the expected element depending on a provided id.
You can make a keyword map and use it instead. As this is static, you can make this map an instance variable and just use it when that method is called.
//do this in something like a constructor
Map<String, String> keywordMap = new HashMap<>;
keywordMap.put("E", "英語");
//more put calls
//and in your method, you'll only need
return keywordMap.get(id.substring(1, 2));
Pay attention to the logic implemented using two switch. As matches in the first switch don't cause the method to return, matches in the second switch can overwrite the keyword variable.
Use a map:
private static final Map<String, String> letterToKeyword =
Map.of("E", "英語", "M", "数学", "W", "統合");
private String getKeyword(String id) {
if (id.substring(4,5).equals("W")) return "統合";
return letterToKeyword.getOrDefault(id.substring(1, 2), "");
}
Prior to Java 9 building the map would be a little more verbose (but could be assisted with a helper method, if so desired):
private static final Map<String, String> letterToKeyword;
static {
Map<String, String> map = new HashMap<>();
map.put("E", "英語");
map.put("M", "数学");
map.put("W", "統合");
letterToKeyword = Collections.unmodifiableMap(map);
}
You could move the body of the switches in separately functions.
you could also remove the break's and return instantly in the cases, if you want it shorter.
You could also use enums
One of your switches can be replaced by a simple if statement.
private String getKeyword(String id)
{
if(id.substring(4,5).equals("W"))
{
return "統合";
}
else
{
switch (id.substring(1, 2)) {
case "E":
return "英語";
case "M":
return "数学";
case "W":
return "統合";
}
}
return "";
}
Related
I have 6 values in the enum and using 6 if-else is really a bad practice.
Can we implement this in any better way? Below is my scenario :
ExampleEnum value = getEnumValue();
if(ExampleEnum.A == value){
doA();
}else if(ExampleEnum.B == value){
doB();
}else if(ExampleEnum.C == value){
doC();
}else if(ExampleEnum.D == value){
doD();
}else if(ExampleEnum.E == value){
doE();
}else if(ExampleEnum.F == value){
doF();
}
I was thinking of switch, but is is not making much difference also i need to return a boolean value inside doA() depending on certain parameters.
Thanks in advance.
You have a few options:
A chain of else-ifs
Leave your code as-is. Hard to read and write.
Switch
switch (value) {
case A:
doA();
break;
case B:
doB();
break;
case C:
doC();
break;
case D:
doD();
break;
case E:
doE();
break;
case F:
doF();
break;
}
Note that this is the classic switch. If you have access to newer Java versions, it is probably possible to get rid of the breaks.
EnumMap
You can also create an EnumMap:
EnumMap<ExampleEnum, Runnable> enumMap = new EnumMap<>(Map.<ExampleEnum, Runnable>of(
ExampleEnum.A, Main::doA, // 'Main', or wherever your do* methods are.
ExampleEnum.B, Main::doB,
ExampleEnum.C, Main::doC, // I'm using method references. But you could
ExampleEnum.D, Main::doD, // also use lambda expressions: '() -> doD()'.
ExampleEnum.E, Main::doE,
ExampleEnum.F, Main::doF
));
ExampleEnum value = getEnumValue();
enumMap.get(value).run();
If you want to use a switch statement and you're on Java 12 or newer, consider using extended switch expressions that avoid the pitfalls of break statements:
switch (value) {
case A -> doA();
case B -> doB();
case C -> doC();
case D -> doD();
case E -> doE();
case F -> doF();
}
You can add the do method inside the enum.
public enum ExampleEnum {
A {
public void doIt() { ... }
},
B {
public void doIt() { ... }
},
...
abstract public void doIt();
}
ExampleEnum value = getEnumValue();
if (value != null) {
value.doIt();
}
I has a method like this
private boolean validGrade(final StringBuilder grade) {
boolean isValid = false;
String semester = "semester";
if ((grade.toString().contains("2o") && grade.toString().contains(semester))
|| (grade.toString().contains("4o") && grade.toString().contains(semester))
|| (grade.toString().contains("6o") && grade.toString().contains(semester))
|| (grade.toString().contains("8o") && grade.toString().contains(semester))) {
isValid = true;
}
}
And I want to replace it witn something like this:
private boolean doValidGradoAntComp(final StringBuilder grade) {
boolean isValid = false;
switch (grade.toString()) {
case "2o semester":
isValid = true;
break;
case "4o semester":
isValid = true;
break;
case "6o semester":
isValid = true;
break;
case "8o semester":
isValid = true;
break;
default:
break;
}
return isValid;
}
And my doubt is:
which one is better?
Both works in the same way?
Why not iterate over the possibilities?
private boolean validGrade(final StringBuilder grade) {
String gradeString = grade.toString();
return List.of("2o", "4o", "6o", "8o")
.stream()
.map(x -> x + " semester")
.collect(Collectors.toSet())
.contains(gradeString);
}
Alternatively, if you're not looking for exact matches, do:
private boolean validGrade(final StringBuilder grade) {
String gradeString = grade.toString();
return gradeString.contains("semester") && List.of("2o", "4o", "6o", "8o")
.stream()
.anyMatch(gradeString::contains);
}
Finally, if your set of matches is inflexible (will always be "2o", "4o", "6o", "8o"), then you can just use a regular expression:
private boolean validGrade(final StringBuilder grade) {
return grade.toString().matches("[2468]o semester"); //exact match
// return grade.toString().matches("[2468]o.*semester|semester.*[2468]o"); //loose match
// return grade.toString().matches(".*([2468]o.*semester|semester.*[2468]o).*"); //equivalent to contains
}
No both the approaches are different, In the first approach you are using contains to check two string existed in grade (For example 2o and semester in grade). But in the second approche you are checking grade is equal to 2o semester. I prefer collecting all those to list and use anyMatch
List<String> list = List.of("2o","4o","6o","8o");
if(list.stream().anyMatch(val->grade.contains(val) && grade.contains(semester))) {
Both serve the same purpose, but each has its differences and weaknesses and strengths.
If / else
Writing and reading difficulty (code is difficult to write because you need to include multivalued checks in one statement)
Your decision to choose is whether your code will be executed or not.
As with the switch, you can create a default statement if its value is not true (else).
Switch
Easy to write and read code.
You will always enter the switch block, if there is no case that matches the value you enter it will default.
You can only use char or int in cases.
You only have one condition, unlike if / else you can have several types of conditions.
Conclusion:
In performance issues the switch is usually faster but the differences are minimal.
If you have few cases to check I would use if/else, but in your case the code you showed is recommended to use the switch case for the number of checks that you do it in one block of code only.
Regex may be slower than if-else or switch. But in your case I would put more value on readability and use regex.
private boolean validGrade(final StringBuilder grade) {
return grade.toString().matches("(2o|4o|6o|8o) semester");
}
Im selecting a "Left" from alert dialog and after putting it into convertStatusToCode function should retrun "4" but its not?
final String[] status = {"Left"};
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Pick a Status");
builder.setItems(status, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
BookingStatus = convertStatusToCode(status[which]);
HERE IS MY convertStatusToCode FUNCTION but it is not retruning "4" which it should return.
private String convertStatusToCode(String status) {
switch (status) {
case "Processing":
i = "0";
break;
case "Room is Allotted":
i = "1";
break;
case "Sorry All Rooms Are Full":
i = "2";
break;
case "Living":
i = "3";
break;
case "Left":
i = "4";
break;
}
return i;
}
it should look something like this
String getStatusCode(String status) {
switch (status) {
case "Processing":
return "0";
case "Room is Allotted":
return "1";
case "Sorry All Rooms Are Full":
return "2";
case "Living":
return "3";
case "Left":
return "4";
default:
return "default_value";
}
}
Based upon what you've added in the comments, your Switch statement (albeit incomplete) shouldn't be the cause of your problem as the other posters are assuming.
You may have a problem with the completness of your switch cases, but that shouldn't stop the switch to work as intended.
You're saying that you DEBUG this and that i has the value of "" which I cannot understand unless you are not having a return value in scope.
The answer posted by Antonis Radz is how I would write that switch if I had to.
If you write your Convert function to return like so, then you don't need the extra i variable, which we don't know where you declared.
If you debug this line of code (like you said you did)
switch(value) and you're telling us that value == "Left" then the switch is receiving the correct value at runtime.
Now your "Case" is executed (when you set a breakpoint in case "Left". So the switch is, again, performing its function so far.
Then I assume you added another breakpoint in the following line(s):
i = "4";
break;
to see what is going on.
The first breakpoint would hit in the assignment i=... and so the variable i which I assume is declared somewhere in scope as String i (At the very least), is either null or contains an old value. Doesn't matter because the next breakpoint (in the break line) would be reached after i is assigned the value of the String "4". So if you add a watch to i and inspect it right there, it must have the value of "4".
Then you return this i so, again, it should still be "4".
If you did all this, you would have been able to tell much closer where the variable is not being assigned.
Do like this.
public String getstatuscode(String status){
String i="";
switch (status) {
case "Processing":
i = "0";
break;
case "Room is Allotted":
i = "1";
break;
case "Sorry All Rooms Are Full":
i = "2";
break;
case "Living":
i = "3";
break;
case "Left":
i = "4";
break;
default:
i = "-1";
}
return i;
}
Declare i as String or int as your requirement. Method is same.Don't forget to remove quotes if you want to assign i as int.
Another thought to use enum rather than switch-case here which gives more flexibility & reusability.
public enum BookingStatus
{
PROCESSING("Processing", 1),
ALLOTED_ROOM("Room is Allotted", 2),
ALL_FULL("Sorry All Rooms Are Full", 3),
LIVING("Living", 4),
LEFT("LEFT", 5);
private String status;
private int code;
BookingStatus(String status, int code)
{
this.status = status;
this.code = code;
}
public static BookingStatus getCodeFromStatus(String status)
{
for (BookingStatus e : values()) {
if (e.status.equals(status)) {
return e;
}
}
return null;
}
public static void main(String args[]) {
System.out.printf("Code for this status is %s", BookingStatus.getCodeFromStatus("Sorry All Rooms Are Full").code);
}
}
switch (status) {
case "Processing":
i = "0";
break;
case "Room is Allotted":
i = "1";
break;
case "Sorry All Rooms Are Full":
i = "2";
break;
case "Living":
i = "3";
break;
case "Left":
i = "4";
// return "4";
break;
}
return i;
}
use return "4"; you don't print anything in switch cases so switch can't return anything if you want to print in switch cases output then use the print method or return in any programming language.
public void select()
{
do
{
switch(info)
{
case'1':
case'a':
return System.out.println("Hello");
case'2':
case'b':
return selection = 'b';
default:
return System.out.println("Close");
}
}while(info != 'b');
}
So what would be the proper syntax and is this the even possible to do. New to Java
First, the loop is not needed, you can delete that. And you are using return statements wrongly. You cannot return
System.out.println();
Also, your method is declared to return void which means nothing. That means your return statement doesn't need anything else,just the word return.
return;
So my advice is that print the stuff first, and then return. And you should really read Java for Dummies, by Barry Burd.
1st of all you can't return anything from a void method, instead change it to char for example:
public char select () {
//read user input
char userInput = '1'; //change it as you wish or read from console
switch (userInput) {
case '1':
case 'a':
return 'a';
case '2':
case 'b':
return 'b';
//... and so on
default:
return '0'; //Or anything you want (but it MUST be a char (at least for my code, if you change it to String, you can return a word or well... a String)).
}
}
Then on main method (or the method which called select()) you add:
char selection;
selection = select();
System.out.println(selection);
If you want to add the switch into a loop (do-while as in your question), then you might want to do it this way on main method:
char selection;
do {
selection = select();
System.out.println(selection);
} while (selection != '0');
However I strongly recommend you to read Java Docs: Switch Statement and Returning a Value from a method which is actually what you're trying to achieve.
From second link you can confirm what I said before (on the 1st line of my answer and as some other users stated on comments)
Any method declared void doesn't return a value.
Hi I am working with the Stack class in java, the problem that I have is that in this Stack I want to insert (to push) elements of type String, but i also want to insert a tree, the code is the following:
public static void Expression(Stack<String> exp)
{
boolean error = false;
String leftExp,rightExp = "";
Stack<String> stackOp = new Stack<String>();
while(!exp.empty() && (error == false))
{
switch(elementType(exp.peek())){
case 'I':
error = true;
break;
case 'O':
if(stackOp.size() < 2)
error = true;
else
{
rightExp = stackOp.pop();
leftExp = stackOp.pop();
Tree subTree = new Tree();
subTree.insertNode(exp.peek());
subTree.insertNode(rightExp);
subTree.insertNode(leftExp);
stackOp.push(subTree);//here is were I have the mistake
}
break;
default:
stackOp.push(exp.peek());
}
}
}
public static char elementType(String car){
char c = 'Z';
if(car.equals("("))
c = 'I';
else if(car.equals(")"))
c = 'D';
else if(car.equals("+") || car.equals("-") || car.equals("*") || car.equals("/"))
c = 'O';
return c;
}
This code basically transforms a math expression into a binary tree, for this I need an input, which is the expression, an output which is the binary tree, and another local stack that contains variables, numbers, and subtrees. But how can i make a Stack that contains elements of different types?
Create a class that can hold anything you want to put on the stack -- I think using a string to designate your operation is a bit clumsy, but suit yourself. If you have a class that is StackElement, it can contain a type indicator (look into Java enums) and methods to do or obtain whatever you want.
You could define StackElement to contain a reference to one of several types, then also define all the methods of all the types it might contain; the ones that apply would be pass-throughs (if the type is an operation, a pass-through for getOperationType()), and the others would throw illegalOperationException, or something. So if you try to call getOperationType() on a value, it throws an exception, same for calling getValue() on an operation, etc.
A nice thing about doing it this way is that you do not have to do any instanceof testing of the types you have stored. You can declare your FILO queue to hold StackElement objects, create them with the types you want, and use them, all without instanceof or otherwise breaking OO style.
public class StackElement
{
private StackElementType type;
private StackOperation operation;
private StackValue value;
public StackElementType getType() { return type; }
public StackOperation getOperation()
{
switch (type)
{
case StackElementType.OPERATION: return operation;
default: throw IllegalOperationException
("getOperation() on type " + type.toString());
}
}
public StackValue getValue()
{
switch (type)
{
case StackElementType.VALUE: return value;
default: throw IllegalOperationException
("getValue on type " + type.toString());
}
}
}