How I should avoid else if in java [duplicate] - java

This question already has answers here:
How to avoid a lot of if else conditions
(8 answers)
Closed 1 year ago.
I've got to do a check in my android app for orientation screen and after that to set the screen orientation to the next phase. I've run out of ideas how to do that avoiding this ugly else if block of code. Could you please give me a suggestion or something?
int currentOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; // Default orientation
.
.
.
switch (item.getItemId()) {
.
.
.
case R.id.change_orientation:
if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
} else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}

Oops, I did not notice Android in your Question. I have no idea whether this works or not in current Android.
tl;dr
this.setRequestedOrientation(
switch ( currentOrientation )
{
case SCREEN_ORIENTATION_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
case SCREEN_ORIENTATION_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
case SCREEN_ORIENTATION_REVERSE_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}
);
Switch expressions
You can use switch expressions in Java 14 and later. The switch can return a value. See JEP 361: Switch Expressions.
Note that switch expressions are “exhaustive”, meaning the compiler tells you if not all of the enum values are covered by your case statements. And therefore no need for a default: case as would otherwise be indicated for defensive programming.
I noticed you call the same method in each of your if cases. So we can move that to a single method call at the end.
package work.basil.enums;
public class App2
{
public static void main ( String[] args )
{
App2 app = new App2();
app.demo();
}
enum ActivityInfo
{
SCREEN_ORIENTATION_PORTRAIT,
SCREEN_ORIENTATION_LANDSCAPE,
SCREEN_ORIENTATION_REVERSE_LANDSCAPE
}
private void demo ()
{
ActivityInfo currentOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
ActivityInfo activityInfo =
switch ( currentOrientation )
{
case SCREEN_ORIENTATION_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
case SCREEN_ORIENTATION_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
case SCREEN_ORIENTATION_REVERSE_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
};
this.setRequestedOrientation( activityInfo );
}
private void setRequestedOrientation ( ActivityInfo activityInfo )
{
System.out.println( "Setting requested orientation to: " + activityInfo );
}
}
Further changes to switch being previewed, in Java 17, by the way. See JEP 406: Pattern Matching for switch (Preview).

Although I don’t understand Android very well, but you can use hashmap to achieve it.
//init a hashmap
Map<String, Map<Integer, Object>> configureMap = Maps.newHashMap();
//itemId means all values in item.getItemId()
configureMap.put("itemId", Maps.newHashMap());
//this can replace your if else in switch
configureMap.get("itemId").put(currentOrientation, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
......
Object orientation = configureMap.get(item.getItemId()).get(currentOrientation);
this.setRequestedOrientation(orientation);
currentOrientation = orientation;
You can also use ImmutableMap.of() to beautify the code.

You can use a map that contains the next orientation value according to the current one:
Map<Integer,Integer> next = new HashMap<>(4);
next.put(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
...
switch (...) {
case R.id.change_orientation:
int nextOrient = next.get(currentOrientation);
this.setRequestedOrientation(nextOrient); // Change this method so it also updates 'currentOrientation'
break;
Note that it would be more efficient to store those next orientation values into an array, search for the index of the current one and then do a (i+1)%4 to get the index of the next one. I'll leave that to you.

Use nested switch block; eg
switch(currentOrientation) {
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
currentOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case y:
// code block
break;
default:
// code block
}
You can know more about switch here: https://www.w3schools.com/java/java_switch.asp
Current currentOrientation is of datatype int [https://developer.android.com/reference/android/content/pm/ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE]
others are also of data type int so comparison can be done, if it was of type Object, then we couldn't use Switch

you can use switch and also use ternatory operator (?) in java.
? operator is used for only 2 conditions. like {condition ? true : false}.
if you have more than one condition than you should go for switch.

Related

Is there a way to search for a value from an assortment of variables using a switch statement?

I am a novice in java, and I am trying to make a search-algorithm for this situation.
I'm attempting to search through a set of 12 integers to find a value equal to 1, similar to this long if-else chain.
if (var1 == 1){
break;
} else if (var2 == 1){
break;
} else if (var3 == 1){
break;
} else if (var4 == 1){
break;
} else if (var5 == 1){
break;
} else if (var6 == 1){
break;
} else if (var7 == 1){
break;
} else if (var8 == 1){
break;
} else if (var9 == 1){
break;
} else if (var10 == 1){
break;
} else if (var11 == 1){
break;
} else if (var12 == 1){
break;
}
However, in an attempt to clean up the code and learn new technique, I am attempting to employ a switch statement to search these variables instead.
The problem I am encountering is that, in order to compare my variables to the constant (1), I feel like I need to use a boolean as the case condition:
switch (){
case var1 == 1: break;
}
However, this throws two errors: there is no expression for the switch statement, and the case condition is a boolean (it expects an int).
The other problem that I've seen is that the case condition must be a constant, meaning I can't have it as a variable:
switch (1){
case var1: break;
}
I think this would trigger if this syntax was correct, but I can't figure out any other ways to do it without using arrays, which I don't really understand.
you need to create an array for your variables
such as
const vars = {1, 2, 3, .. etc}
then you can use for loop
for(let i=0; i<vars.length; i++){
if(vars[i] == 1){
// things you want to do
break();
}
}
switch-statements and switch-expressions are useful when you need to define multiple execution paths depending on the value of a single variable (for more information, refer to the official tutorial), but in your can cause you need to operate with multiple variables.
As a possible solution, you can collect these variable into an array or a List, and then check if it contains a value of 1.
Example:
List<Integer> vars = List.of(var1, var2, var3, ... );
...
if (vars.contains(1)) { ... }
i prefer to use HashMap because the complexity is o(1), so you can get it directly by using the constant key, for ex:
private final int KEY = 1;
Map<Integer, Integer> testMap = new HashMap<>();
// populate testMap
Integer result = testMap.get(KEY);
def search(value):
var1 = 'apple'
var2 = 'banana'
var3 = 'cherry'
if found:
print(f'{value} was found!')
else:
print(f'{value} was not found.')
search('apple')
search('orange')
You can use the functional programming approach in Java to iterate over a given set of items.
for example:
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
// Adding items to this set for demonstration purposes.
// In your case the given Set is already populated
Set<Integer> filteredSet = set.stream().filter(item -> item == 1).collect(Collectors.toSet());
filteredSet.forEach(item -> {
System.out.println("Item: " + item);
});
Explanation:
set.stream() opens a Stream for the given Items in this set.
stream().filter(x -> x == 1) filteres all items, which are not applying to the given filter-function "x -> x == 1".
This filter-function essentially defines an "item" which then can be compared to the value of 1 through the "equals"-Operator.
The method "collect(Collectors.toSet())" takes all the filtered items (in this case its only the Integer of the value 1) and assigns those values to the new Set "filteredSet".
After that the given filteredSet is being iterated over via the functional Method "forEach()" which then prints all values of the given Set. (in this case only 1 value of "1")

Inline switch statement java?

Is there a way to implement an inline switch statement in java?
Right now, i'm using the following:
private static String BaseURL = (lifeCycle == LifeCycle.Production)
? prodUrl
: ( (lifeCycle == LifeCycle.Development)
? devUrl
: ( (lifeCycle == LifeCycle.LocalDevelopment)
? localDevUrl
: null
)
);
I would much prefer it if I could do something like:
private static String BaseURL = switch (lifeCycle) {
case Production: return prodUrl;
case Development: return devUrl;
case LocalDevelopment: return localDevUrl;
}
I do know you could achieve this by moving the BaseURL variable into a function GetBaseURL where the switch occurs (see below), however I'm more so just curious if this feature even exists in Java.
static String GetBaseURL() {
switch(lifeCycle) {
case Production: return prodUrl;
case Development: return devUrl;
case LocalDevelopment: return localDevUrl;
}
return null;
}
I'm transitioning from Swift, and in Swift I know you could do this:
private static var BaseURL:String {
switch (API.LifeCycle) {
case .Production:
return prodUrl
case .Development:
return devUrl
case .LocalDevelopment:
return localDevUrl
}
}
Assuming LifeCycle is an enum, then you're in luck, as switch expressions were introduced as a preview feature in JDK 12. By using them, your code would look like the following:
LifeCycle lifeCycle = ...;
String baseURL = switch (lifeCycle) {
case Production -> prodUrl;
case Development -> devUrl;
case LocalDevelopment -> localDevUrl;
};
If the LifeCycle enum contains more than those three values, then you'll need to add a default case; otherwise, it will be a compile-time error.

Switch case error on libs

I have an error on implementing a library module to my Android apps.
it says:
Constant expression required Resource IDs cannot be used in a switch statement in Android library modules less... (Ctrl+F1)
Validates using resource IDs in a switch statement in Android library module. Resource IDs are non final in the library projects since SDK tools r14, means that the library code cannot treat these IDs as constants.
and here is my code:
private void changeWeekStart(#IdRes int selection) {
switch (selection) {
case R.id.action_week_start_saturday:
CalendarUtils.sWeekStart = Calendar.SATURDAY;
break;
case R.id.action_week_start_sunday:
CalendarUtils.sWeekStart = Calendar.SUNDAY;
break;
case R.id.action_week_start_monday:
CalendarUtils.sWeekStart = Calendar.MONDAY;
break;
}
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putInt(CalendarUtils.PREF_WEEK_START, CalendarUtils.sWeekStart)
.apply();
supportInvalidateOptionsMenu();
mCoordinator.reset();
}
Please help me to change from switch-case to if-else code.
thanks.
Everywhere you have a case, that will become the condition of an if statement; a break statement will correspond with a closing } on an if statement.
if (selection == R.id.action_week_start_saturday) {
CalendarUtils.sWeekStart = Calendar.SATURDAY;
} else if (selection == R.id.action_week_start_sunday) {
CalendarUtils.sWeekStart = Calendar.SUNDAY;
} else if (selection == R.id.action_week_start_monday) {
CalendarUtils.sWeekStart = Calendar.MONDAY;
}
Note that you do not supply a default case in your switch-case block so it is possible that CalendarUtils.sWeekStart is not modified if the selection parameter has a value different from the ones you've considered.

How to remove value from ArrayList<String> when another checkbox is checked

I have tried a couple of ways to remove the value from the array list once the checkbox is deselected but seems I still have not succeeded.
The code below contains a switch statement that will hold our cases for each box. Basically when the user selects one of the boxes it stores the value into the ArrayList<String> and then I store access it's value in another method using messageTotalTip = selection.get(0);
Thanks in advance!
/* Create a View for our Check Boxes */
public void selectTip(View view){
/*Boolean object will check if our checkbox is checked or not*/
boolean checked =((CheckBox) view).isChecked();
switch (view.getId()){
/*Case if 15% is clicked*/
case R.id.cb15Percent:
if(checked){
/*store our value into the ArrayList*/
selection.add("15");
/*To make sure we cant click any other box*/
cb18Percent.setChecked(false);
cb20Percent.setChecked(false);
cbCustomTip.setChecked(false);
/*Try and make sure that our value is erased if unchecked */
if(cb18Percent.isChecked() || cb20Percent.isChecked()||cbCustomTip.isChecked()) {
selection.remove("15");
}
} else {
selection.remove("15");
}
break;
/*Case if 18% is clicked*/
case R.id.cb18Percent:
if(checked){
/*store our value into the ArrayList*/
selection.add("18");
/*Make sure we cant click any other box*/
cb15Percent.setChecked(false);
cb20Percent.setChecked(false);
cbCustomTip.setChecked(false);
/*Try and make sure that our value is erased if unchecked */
if(cb15Percent.isChecked() || cb20Percent.isChecked()||cbCustomTip.isChecked()) {
selection.remove("18");
}
} else {
selection.remove("18");
}
break;
/*Case if 20% is clicked*/
case R.id.cb20Percent:
if(checked) {
/*store our value into the ArrayList*/
selection.add("20");
/*Make sure we cant click any other box*/
cb15Percent.setChecked(false);
cb18Percent.setChecked(false);
cbCustomTip.setChecked(false);
/*Try and make sure that our value is erased if unchecked */
if(cb18Percent.isChecked() || cb15Percent.isChecked()||cbCustomTip.isChecked()) {
selection.remove("20");
}
} else {
selection.remove("20");
}
break;
/*Case if the custom box is checked*/ /************ Add dialogue box later once smaller bugs are fixed ************/
case R.id.cbCustom:
if(checked){
selection.add("100");
/*Make sure we cant click any other box*/
cb15Percent.setChecked(false);
cb18Percent.setChecked(false);
cb20Percent.setChecked(false);
/*Try and make sure that our value is erased if unchecked */
if(cb18Percent.isChecked() || cb20Percent.isChecked()||cb15Percent.isChecked()) {
selection.remove("100");
}
}else {
selection.remove("100");
}
}
}
UPDATE:
A big thanks to all you guys. I figured out what I was doing wrong. I was using a different approach before I wrote this post that made me use an ArrayList. After seeing some of your guys comments I realized I didn't need the ArrayList anymore.
FIX: Pretty much just set a global variable called messageTotalTip and set the value of it depending on the case.
Thank you all!

In Java is there a way to auto detect how many cases there are in a switch operation?

In my Java app, I have a switch method, the app needs to loop through all the cases in the switch, but the switch method keeps changing as my app develops, so I wonder if there is a way to auto detect how many cases there are in the switch and loop through all of them.
void RunAllCases(){
for (int i=0;i< ?? ;i++) SwitchMethod(i);
}
...
int SwitchMethod(int I)
{
switch (I) {
case 0 : return x;
case 1 : return y;
...
case 200 : return xx;
...
case 360 : return yy;
...
case 778899 : return nnnnn;
...
default : return z;
}
}
x, y, xx, yy, etc. are some calculated int values.
The short answer - no.
The slightly longer answer - not with an int. What you could do, though, is define an enum and pass that to the switchMethod. Then it can easily be iterated over by calling values():
public enum SwitchCases {
Case1, Case2, etc;
}
void runAllCases() {
for (SwitchCases sc : SwitchCases.values()) {
switchMethod(sc);
}
}
int switchMethod(SwitchCases sc) {
switch (sc) {
case Case1: return x;
case Case2: return y;
// etc...
}
}
If your app has all these switch statements, and you want to 'hit' all of them, then why not just define a method that calls each of them directly, in turn?
First of all, your requirement in this question is the switch case itself so we can't write anything inside the switch case. And you can't detect the number of checks inside the switch from outside.
Otherwise, if you yourself is writing the switch case then u can write all the cases without break and while calling call the first case and it will execute all the cases.

Categories