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.
Related
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.
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();
}
One of the best things about Optional is it saves all the boilerplate checking for null values in a long chain:
Optional.ofNullable(myService.getSomething())
.map(secondService::fetch)
.map(thirdService::fetchAgain)
// And so forth...
At any point the Optional will jump onto the 'empty' track if map returns a null.
It would be great if something similar could be done for Strings instead of having to check them for String::isEmpty every time:
Optional.ofNullable(entity.getName())
.filter(String::isEmpty)
.map(Utils::performSomeOperation)
.filter(String::isEmpty)
.or(service::getMostCommonName)
.filter(String::isEmpty)
.orElse("Bob");
Something like this:
OptionalString.ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
The key logic in Optional happens in ofNullable when it calls its check for value == null. Theoretically you could apply any sort of logic in there:
MagicalOptionalString(StringUtils::isNotBlank).ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
However, Optional is final, preventing any straightforward way of extending this behaviour. So is there an existing, robust implementation of this out there already?
Trying out a few things to resolve what you were aiming at, and realizing that I would second the thought from VGR as implementing such a use case is a lot of extra work as compared to using the existing methods.
Yet, few details that I could add to after spending some time looking over the implementations -
As a utility, you could implement a static implementation which verifies for both null and isEmpty condition for a string input and returns Optional accordingly. The code could look something like -
private static Optional<String> ofEmptyable(String string) {
return isNullOrEmpty(string) ? Optional.empty() : Optional.of(string);
}
private static boolean isNullOrEmpty(String target) {
return target == null || target.isEmpty();
}
this could then replace the usage of the ofNullable which specifically checks for null(the primary purpose of Optional).
Since the expectations in your problem statement were to actually handle the cases per method(map/or/orElse) call as in the optional, one approach similar to OptionalInt could be to implement a custom OptionalString as -
public final class OptionalString {
private static final OptionalString EMPTY = new OptionalString();
private final boolean isPresent;
private final String value;
private OptionalString() {
this.isPresent = false;
this.value = "";
}
private static OptionalString empty() {
return EMPTY;
}
private boolean isPresent() {
return isPresent;
}
private OptionalString(String value) {
this.isPresent = true;
this.value = value;
}
public static OptionalString of(String value) {
return value == null || value.isEmpty() ? OptionalString.empty() : new OptionalString(value);
}
public OptionalString map(Function<? super String, ? extends String> mapper) {
return !isPresent() ? OptionalString.empty() : OptionalString.of(mapper.apply(this.value));
}
public OptionalString or(Supplier<String> supplier) {
return isPresent() ? this : OptionalString.of(supplier.get());
}
String orElse(String other) {
return isPresent ? value : other;
}
public String getAsString() {
return Optional.of(value).orElseThrow(() -> new NoSuchElementException("No value present"));
}
}
which could be further implemented for your use case in the following manner -
String customImpl = OptionalString.of(entity.getName())
.map(OptionalStringTest::trimWhiteSpaces) // OptionalStringTest is my test class name where 'trimWhiteSpaces' operation on String resides
.or(service::getMostCommonName)
.orElse("learning");
System.out.println(String.format("custom implementation - %s", customImpl));
where
private static String trimWhiteSpaces(String x) {
return x.trim();
}
Note - Honestly, I couldn't find the rationale behind not having an OptionalString class upfront in the JDK (the reason why I am stating this is because I suspect there definitely must have been a thought behind it), I believe its just that the radius of my reach is much smaller and I would expect someone credible to add to the details here. IMHO, it seems more like almost all of what you desire is right there using the Optional<String> and which takes us back to the starting of the loop.
For anyone working in Kotlin, this is really easy to do:
class NonEmptyString private constructor(val Email: String) {
companion object Factory {
operator fun invoke(value: String?): T? = value?.let { if (it.isNotEmpty()) NonEmptyString(value) else null }
}
}
The "static" invoke function conditionally creates a new object depending on whether it's valid or not. And allows you to call it like a constructor (NonEmptyString(value)). The private constructor forces you to use the invoke method.
Because this returns a null if it's not valid, and Kotlin has null-safety built in, it can be really easy to chain. Adding map or flatMap functions is then pretty straight-forward.
See this Code Review question for a more comprehensive, generalisable example I wrote.
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 "";
}
Is there a better way to negate a boolean in Java than a simple if-else?
if (theBoolean) {
theBoolean = false;
} else {
theBoolean = true;
}
theBoolean = !theBoolean;
theBoolean ^= true;
Fewer keystrokes if your variable is longer than four letters
Edit: code tends to return useful results when used as Google search terms. The code above doesn't. For those who need it, it's bitwise XOR as described here.
There are several
The "obvious" way (for most people)
theBoolean = !theBoolean;
The "shortest" way (most of the time)
theBoolean ^= true;
The "most visual" way (most uncertainly)
theBoolean = theBoolean ? false : true;
Extra: Toggle and use in a method call
theMethod( theBoolean ^= true );
Since the assignment operator always returns what has been assigned, this will toggle the value via the bitwise operator, and then return the newly assigned value to be used in the method call.
This answer came up when searching for "java invert boolean function". The example below will prevent certain static analysis tools from failing builds due to branching logic. This is useful if you need to invert a boolean and haven't built out comprehensive unit tests ;)
Boolean.valueOf(aBool).equals(false)
or alternatively:
Boolean.FALSE.equals(aBool)
or
Boolean.FALSE::equals
If you use Boolean NULL values and consider them false, try this:
static public boolean toggle(Boolean aBoolean) {
if (aBoolean == null) return true;
else return !aBoolean;
}
If you are not handing Boolean NULL values, try this:
static public boolean toggle(boolean aBoolean) {
return !aBoolean;
}
These are the cleanest because they show the intent in the method signature, are easier to read compared to the ! operator, and can be easily debugged.
Usage
boolean bTrue = true
boolean bFalse = false
boolean bNull = null
toggle(bTrue) // == false
toggle(bFalse) // == true
toggle(bNull) // == true
Of course, if you use Groovy or a language that allows extension methods, you can register an extension and simply do:
Boolean b = false
b = b.toggle() // == true
The class BooleanUtils supportes the negation of a boolean. You find this class in commons-lang:commons-lang
BooleanUtils.negate(theBoolean)
Boolean original = null; // = Boolean.FALSE; // = Boolean.TRUE;
Boolean inverse = original == null ? null : !original;
If you're not doing anything particularly professional you can always use a Util class. Ex, a util class from a project for a class.
public class Util {
public Util() {}
public boolean flip(boolean bool) { return !bool; }
public void sop(String str) { System.out.println(str); }
}
then just create a Util object
Util u = new Util();
and have something for the return System.out.println( u.flip(bool) );
If you're gonna end up using the same thing over and over, use a method, and especially if it's across projects, make a Util class. Dunno what the industry standard is however. (Experienced programmers feel free to correct me)
Before:
boolean result = isresult();
if (result) {
result = false;
} else {
result = true;
}
After:
boolean result = isresult();
result ^= true;