Lots of If conditions in Java - java

I've just started learning java and have a really basic question. I have a label that I want to change colors when a random integer between 1 and 18 lands on a particular number. These numbers are not odd or even, so I can't use that.
Right now I have this:
if (Random == 1 || Random == 2 || Random == 5 || Random == 7 || Random == 12 || Random == 14 || Random == 16 || Random == 18)
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
else if (Random == 3 || Random == 4 || Random == 6 || Random == 8 || || Random == 9 | Random == 10 || Random == 11 || Random == 13 || Random == 15 || Random == 17)
label_wheelNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
I know it looks silly, and I feel like an idiot doing it this way. What do you recommend? I haven't taken a class so any explanations are extremely useful. Thanks

Here is an example of a switch:
Note the break; when using a switch, the case will fall through. Essentially, case 1: will fall through to the next code block. For example in my code, in case 5: if the break; was not there, it would fall through to the next code block and end up with the second code block containing SWT.COLOR_GREEN being called as well.
switch(Random)
{
case 1:
case 2:
case 5:
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
break;
case 9:
case 10:
label_wheelNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
break;
}

You may use a switch:
switch(Random) {
case 1: case 2: case 5: case 7: case 12: case 14: case 16: case 18:
//something...
break;
case 3: case 4: case 6: case 8: case 9: case 10: case 11: case 13: case 15: case 17:
//something...
break;
default:
//just in case none of the over values was selected
}
If the values may vary fast or you want to allow more values, you can store them in an array or similar:
static final int[] FOREGROUND_BLUE = {1, 2, 5, 7, 12, 14, 16, 18};
static final int[] FOREGROUND_GREEN = {3, 4, 6, 8, 9, 10, 11, 13, 15, 17};
And then perform a search to seek if the value belongs to the specified array:
//using binary search since the data in the array is already sorted
int found = Arrays.binarySearch(FOREGROUND_BLUE, Random);
if (found >= 0) {
//something...
}
found = Arrays.binarySearch(FOREGROUND_GREEN, Random);
if (found >= 0) {
//something...
} else {
//...
}
In case you can even have more options, probably you want to use a cache-like approach and store the data in a Map<Integer, Color>:
static final Map<Integer, Color> colorMap;
static {
Map<Integer, Color> colorMapData = new HashMap<Integer, Color>();
Color blue = SWTResourceManager.getColor(SWT.COLOR_BLUE);
Color green = SWTResourceManager.getColor(SWT.COLOR_GREEN);
colorMapData.put(1, blue);
colorMapData.put(2, blue);
colorMapData.put(3, green);
colorMapData.put(4, green);
colorMapData.put(5, blue);
//...
//this makes colorMap truly constant and its values cannot be modified
colorMap = Collections.unmodifiableMap(colorMapData);
}
And then you just call the value from map:
Color = colorMap.get(Random);

Use a Switch statement:
public class SwitchDemo {
public static void main(String[] args) {
int month = 8;
String monthString;
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
case 4: monthString = "April";
break;
case 5: monthString = "May";
break;
case 6: monthString = "June";
break;
case 7: monthString = "July";
break;
case 8: monthString = "August";
break;
case 9: monthString = "September";
break;
case 10: monthString = "October";
break;
case 11: monthString = "November";
break;
case 12: monthString = "December";
break;
default: monthString = "Invalid month";
break;
}
System.out.println(monthString);
}
}
Taken from: Oracle's Java Tutorial.

There may be better options depending on where Random is coming from and in what context this is happening, but one option you have to do basically the same thing with a different syntax is:
switch(Random) {
case 1:
case 2:
case 5:
case 7:
case 12:
case 14:
case 16:
case 18:
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
break;
case 3:
case 4:
case 6:
case 8:
case 9:
case 10:
case 11:
case 13:
case 15:
case 17:
label_wheelNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
break;
}
That is only marginally better than what you have but I think it is at least a little easier to look at.

Use a lookup list:
int[] ALLOW_BLUE = {1,2,5,7,12,14,16,18};
int[] ALLOW_GREEN = {3,4,6,8,9,10,11,13,15,17};
if(Arrays.asList(ALLOW_BLUE).contains(random){
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
}
else if(Arrays.asList(ALLOW_GREEN).contains(random){
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
}

Switch case will do but another way you can do is
int[] blueArray ={1,2,5,7,12,14,16,18};
if(Utils.arrayContain(blueArray,Random)){//your util method
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
}elseif(){
}
Take your possible values in an array and check Random is there in that value or not.

If you use a map you can turn this into a one-liner (eliminate the if/switch completely).
HashMap<Integer, Color> mp = new HashMap<Integer, Color>();
mp.put(1, SWT.COLOR_BLUE);
mp.put(2, SWT.COLOR_BLUE);
...
mp.put(18, SWT.COLOR_BLUE);
mp.put(3, SWT.COLOR_GREEN);
mp.put(4, SWT.COLOR_GREEN);
...
mp.put(17, SWT.COLOR_GREEN);
...
label_number.setForeground(SWTResourceManager.getColor(mp.get(Random)));
Also, name your Random variable differently as it clashes with a class name from the Java API.

A more elegant way would be to place each group of numbers in an ArrayList and then check if the Random number is contained in the array with the contains() method:
if(Arrays.asList(new Integer[]{1, 2, 5, 7, 12, 14, 16, 18}).contains(Random )) {
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
} else if (Arrays.asList(new Integer[]{3, 4, 6, 8, 9, 10, 11, 13, 15, 17}).contains(Random)) {
label_wheelNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
}
For performance concerns you can also declare and store these arrays separately instead of creating them on the fly everytime you want to make the comparison.

For situations where you can't use a switch but you still have some complicated condition to evaluate you can use an "explanatory variable"
// before
if ( a && b || c != d && e > f && g < h && h == 1 ) {
doSomething();
} else if ( i && j || etc ) {
doSomethingElse();
}
//after with a variable
boolean shouldDoSomething = a && b || c != d && e > f && g < h && h == 1;
if ( shuoldDoSomething ) {
doSomething();
} else if ( i && j || etc ) {
doSomethingElse();
}
Or create a method that evaluates the condition:
// after with a method
if ( shouldDoSomething(a,b,c,d,e,f,g,h) ) {
doSomething();
} else if ( shouldDoSomethingElse(i, j, etc )) {
doSomethingElse();
}
...
private boolean shouldDoSomething( boolean a,boolean b,int c,int d,int e,int f,int g,int h) {
return a && b || c != d && e > f && g < h && h == 1;
}
private boolean shouldSoSomethingElse(boolean i, boolean j, boolean etc ) {
return i && j || etc;
}
The objective is to simplify your code allowing you to understand it better and making it easier to modify a less error prone. If using a variable or creating a method is more confusing then continue with the simple evaluation. You can also combine the three:
//
boolean shouldDoX = a || b;
if ( shouldDoX || e != d && inRange(f, g, h ) ) {
doSomething();
}
Again the objective is to make it easier to maintain.
In this example the variables are a, b, c but in real code you should use a short meaningful variable name
if ( inRange(random) ) {
label_number.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
} else if ( outOfRange(random)) {
label_wheelNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_GREEN));
}
...
private boolean inRange(int random ) {
// use switch or simple return random == 1 || random == 2 etc.
}
Also, final notes on style: do always use brace on your if's even if they are one line and keep the opening brace in the same line. In Java, variables start with lowercase and are written in camelStyle ( no underscores ). These are just style conventions and will help you to create good habits. Each language has its own conventions, learn them and use them.

Related

Bad practice when I want to check like this if an int is this number?

I have to check if my int n equals 1 or 2 or 3 or 4 or 5 or 6
Is it bad practice to do it like this:
//n = randomnumber
private final List<Integer> numbers = Arrays.asList(0,1,2,3,4,5,6);
if(numbers.contains(n)){
return;
}
or should I do a switch?
switch(n){
case 1:
return;
break;
case 2:
return;
break;
//...
case 6:
return;
break;
}
I could also do if statmements but I guess I dont have to

How to NOT return value in INT method?

When I run the code it returns:
31 and -1
How can I get rid of -1? Is there a way NOT to return in method INT? I tried to return java.lang.Integer(null) but it gave me an error. I think I used it in a wrong way.
Here is the code:
package com.company;
public class Main {
public static void main(String[] args) {
int y = getDaysInMonth(1, 2020);
System.out.println(y);
}
public static boolean isLeapYear(int year) {
if (year > 1 && year < 9999) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return true;
}
return false;
}
return false;
}
public static int getDaysInMonth(int month, int year) {
if ((month < 1 || month > 12) && (year < 1 || year > 9999)) {
return -1;
} else if (!isLeapYear(year)) {
switch (month) {
case 1:
System.out.println(31);
break;
case 2:
System.out.println(28);
break;
case 3:
System.out.println(31);
break;
case 4:
System.out.println(30);
break;
case 5:
System.out.println(31);
break;
case 6:
System.out.println(30);
break;
case 7:
System.out.println(31);
break;
case 8:
System.out.println(31);
break;
case 9:
System.out.println(30);
break;
case 10:
System.out.println(31);
break;
case 11:
System.out.println(30);
break;
case 12:
System.out.println(31);
break;
default:
return -1;
}
} else if (isLeapYear(year)) {
switch (month) {
case 1:
System.out.println(31);
break;
case 2:
System.out.println(29);
break;
case 3:
System.out.println(31);
break;
case 4:
System.out.println(30);
break;
case 5:
System.out.println(31);
break;
case 6:
System.out.println(30);
break;
case 7:
System.out.println(31);
break;
case 8:
System.out.println(31);
break;
case 9:
System.out.println(30);
break;
case 10:
System.out.println(31);
break;
case 11:
System.out.println(30);
break;
case 12:
System.out.println(31);
break;
default:
return -1;
}
} else return -1;
return -1;
}
}
I tried almost everything there should be something that I don't know yet.
This is because you are printing first in the method and then printing again the returned value of the method in y.
Instead of printing every time, try returning the values. Also the program you have written could be written much efficiently.
Here is an example :
public static int getDays(int monthNumber, int yearNumber)
{
if (monthNumber == 2 && !isLeapYear(yearNumber))
return 28;
else if (monthNumber==2)
return 29;
else if ((monthNumber >= 1) && (monthNumber <= 7) && (monthNumber % 2 ==1))
return 31;
else if ((monthNumber >= 8) && (monthNumber %2==0))
return 31;
else
return 30;
}
Is there a way NOT to return in method INT?
Yea, sure. Throw an exception. For an example:
if (month < 1 || month > 12) {
throw new IllegalArgumentException("month value is out of range");
}
(Hint: I noted a bug in your existing error checking. Look carefully at it when you rewrite it.)
Throwing an exception causes the method to terminate without returning any result. Even if the method signature says that a result should be returned. You can read about it in the Oracle Java Tutorials: https://docs.oracle.com/javase/tutorial/essential/exceptions/definition.html. That part of the Java Tutorials explains what exceptions are, how and when to throw them, how to catch them, and what happens when you don't catch them.
Having said that, there are a few places where you are returning -1. You need to check each one carefully to decide if it is actually possible. If the inputs to getDaysInMonth are valid, then you should always be able to compute a "days in the month" value. And you should only need to check the arguments in one place.
My recommendation would be check the argument values at the start of the method. The rest of the method can then be coded on the assumption that the arguments are valid.
Finally, if the getDaysInMonth is returning -1 for getDaysInMonth(1, 2020) that indicates that you have a bug in the logic of the method. I recommend you use a debugger to find it ... if you can't spot it by reading and logically analyzing your code.
Looking carefully at your function, as it is now, it will always return -1 and nothing else.
A function declared public static int getDaysInMonth(int month, int year) must return an int value, if it completes successfully.
The only case it may exit without returning a value is by throwing an exception.
So, I am going to assume your function needs to return the number of day in the month and not just print it.
Here is the code for that which will never return -1, or any value other than 28, 29, 30, 31:
public static int getDaysInMonth(int month, int year) throws IllegalArgumentException {
if (year < 1 || year > 9999) {
throw new IllegalArgumentException(String.format("Invalid year %d must be between 1 and 9999", year));
}
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
System.out.println(31);
return 31;
case 2:
if (isLeapYear(year)) {
System.out.println(29);
return 29;
} else {
System.out.println(28);
return 28;
}
case 4:
case 6:
case 9:
case 11:
System.out.println(30);
return 30;
}
throw new IllegalArgumentException(String.format("Invalid month %d must be between 1 and 12", month));
}
Note the following changes:
case in Java is "fall through" which means you don't have to write the same code over and over, you can put cases with same result one below the other without the brake statement and they will all work together to give the same result.
At the beginning of the function we only check if the year is valid. If the month is invalid non of the case statements will execute and the code will go directly to the line after the switch block. At that point we know the month is not valid, so no need to check, just trow the exception.
Any function that throws an exception must declare that it does so in the function header, by adding throws clause and listing the exceptions separated by commas.
When you call a function that throws an exception, you must wrap it in try .. catrch block.
Java methods can return only one type of result: https://www.javatpoint.com/method-in-java
Return Type: Return type is a data type that the method returns. It may have a primitive data type, object, collection, void, etc. If the method does not return anything, we use void keyword.
As a workaround:
Use the wrapper class
You can use the Integer class as a return type and return null. It's not much better than -1 but it indicates that nothing was returned.
Invalid argument exception
Throw this: https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalArgumentException.html it's what it's made for
default:
throw new IllegalArgumentException("Invalid month value - out of range");
Create enum
Create an enum type and have it as a parameter in your method. That way there won't be any way to have an unknown value.
public enum Month {
January(1), February(2), March(3), April(4),May(5),June(6), July(7), August(8), September(9), October(10), November(11), December(12)
}

How to use switch in array comparison? [duplicate]

This question already has answers here:
Using switch statement with a range of value in each case?
(20 answers)
Closed 7 years ago.
I want to compare array length with some int values. I can do it with if else but how to do it with switch because switch is fast and I want to use that in my project
switch (array.length) {
case array.length <= 11: // how to do this
break;
default:
break;
}
With if else I can do this:
if (array.length <= 5) {
//my is code here
}
else if (array.length <= 15) {
//my is code here
}
else if (array.length <= 10) {
//my is code here
}
You can't. switch can only test exact values.
You could do:
switch(array.length) {
case 0: case 1: case 2: case 3:
case 4: case 5: case 6: case 7:
case 8: case 9: case 10: case 11:
// do stuff
break;
default:
break;
}
But why do you want to do this? What makes you think it's faster?
switch is not the same as if (...) { ... } else { ... }. You can only use == within a case. You would have to do something like this:
int length = array.length;
switch (length) {
case 0:
case 1:
case 2:
[...]
case 11:
// your code here
break;
//other cases here
}
Notice the missing break-statements, they are quite important.
I would recommend this tutorial for more details.
You can't do it(as per your example) using switch. Since the values of case are constant expression (case *value*).
Switch statements operate by exact matches rather than comparisons like if does. You can do what you want by introducing a new variable like this:
int value = (array.length <= 11 ? 0 : (array.length <= 20 ? 1 : 2));
switch (value) {
case 0: // 11 or under
break;
case 1: // 12 to 20
break;
case 2: // 21 or more
break;
}
I don't know if this buys you much over if/else statements, but if you find it cleaner to code, you can do it.
In your if/elseif, the if(array.length<=10) will never run because if(array.length<=15) is checked above it.
Doing this with an if/elseif structure would require less lines of code.
If you want to do this using a switch/case statement, this would work:
int length = array.length;
switch(length) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5: {
System.out.println("Case 0<=length<=5 triggered.");
break;
}
case 6:
case 7:
case 8:
case 9:
case 10: {
System.out.println("Case 6<=length<=10 triggered.");
break;
}
case 11:
case 12:
case 13:
case 14:
case 15: {
System.out.println("Case 10<=length<=15 triggered.");
break;
}
default: {
System.out.println("Default case triggered.");
}
}

Assigning a name to a number

I'm currently writing a program involving random card selection and I'm wondering if there is a way to get the program to replace the numbers 11, 12, and 13 with jack, queen and king respectively? I could use an if statement to detect values greater than 10 but that would force me to write the same code around 4 times which seems counterproductive. Any and all responses greatly appreciated!
int card0 = (cardGenerator.nextInt(13) + 2);
int winTest = 4;
while(winTest > 0)
{
Object[] highLowEqual = { "higher", "lower", "equal", "Quit" };
Object userChoice = JOptionPane.showInputDialog(null,
"The current card is " + card0 + ". Which do you think the next card will be? Remember: Ace is the highest possible.", "HiLo",
JOptionPane.INFORMATION_MESSAGE, null,
highLowEqual, highLowEqual[0]);
int card1 = (cardGenerator.nextInt(13) + 2);
Have a Card class that knows how to print itself:
public class Card
{
int rank;
// ...
public String toString()
{
switch( rank )
{
case 1: return "Ace";
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10: return "" + rank;
case 11: return "Jack";
case 12: return "Queen";
case 13: return "King";
default: return "INVALID CARD RANK";
}
}
}
Some piece of code has to do the replacement and that code has to go somewhere. As commented by khelwood and answered by clcto, you can possibly override the toString() method and put the logic for replacement in there.

Switch statement

How can I add conditions into a switch statement?(ex:-Displaying the grade for the average marks)
I recommend using if-else... switch statements can only compare on equality.
With an integer score, you COULD do something like...
switch (score)
{
case 100:
case 99:
case 98:
case 97:
case 96:
case 95:
case 94:
case 93:
case 92:
case 91:
case 90:
grade = 'A';
break;
case 89:
/* ... */
}
See the problem? :-)
You can't. Use an if-else-if-else.
Here is how I use less than greater than in a switch statement. The following is in actionscript 3...
var unknown1:Number = 8;
var unknown2:Number = 2;
var lowerBoundary = 1;
var upperBoundary = 5
switch(true){
case (unknown2 < lowerBoundary || unknown2 > upperBoundary):
trace("value is out of bounds");
break;
case (unknown2 > lowerBoundary && unknown2 < upperBoundary):
trace("value is between bounds");
break;
default:
trace("Out of Luck");
break;
}
Output...
value is between bounds
This question is listed with a Java tag so...
Generic switch statement:
// ... within class scope
private final int CONSTANT_1 = 1;
private final int CONSTANT_2 = 2;
private final int CONSTANT_3 = 3;
// ...
public void doStuff(MyObject myObject){
int variable = myObject.getIntValue();
switch(variable){
case CONSTANT_1:
System.out.println(variable + " is equal to " + CONSTANT_1);
// use a break statement to tell the switch to stop here
// or else it will execute all subsequent cases:
break;
case CONSTANT_2:
System.out.println(variable + " is equal to " + CONSTANT_2);
// what happens if I leave out the break?
case CONSTANT_3:
System.out.println(variable + " is equal to " + CONSTANT_2);
break;
default:
System.out.println(variable + " wasn't equal to anything!");
}
Let's say I run through this 3 times and "myObject.getIntValue()" returns these values in this order; 3, 1, 2, and finally 42. Then the following output would be generated:
First time through using the value '3'...
3 is equal to 3
Second time through using the value '1'...
1 is equal to 1
Third time through using the value '2'...
2 is equal to 2
2 is equal to 3
Fourth time through using the value '42' ...
42 wasn't equal to anything!
Notice the third run has two lines (and one incorrect one) because I left out the break keyword for the second case.
Now in Java 1.5 and up, you can also switch on the Enum type:
public void doStuff(MyObject myObject){
MyEnumType varType = myObject.getEnum();
switch(varType){
case MyTypeOne:
// everything else is the same -- nothing special here.
// put whatever code you want in.
break;
case MyTypeTwo:
// everything else is the same -- nothing special here.
// put whatever code you want in.
break;
case MyTypeThree:
// everything else is the same -- nothing special here.
// put whatever code you want in.
break;
default:
// code for unknown case goes here
}
}
Depending on what your ranges are you can use a formula.
e.g.
switch(score/10) {
case 10: case 9: case 8: return 'A';
case 7: return 'B';
case 6: return 'C';
case 5: return 'D';
default: return 'U';
}
In this example, does the code generate a random number and do something if it's that number or that number.
int num; //Just declares a variable
Random r = new Random(); //This makes an object that generates random numbers.
num = r.nextInt(2); //This "Choose" the random number. The possible numbers are 0 and 1. and the sets the the num variable to the number.
switch(num){
case 0: //This says if the number is 0 then do this.
//put code here.
break;
case 1: //This says if the number is 1 then do this.
//put code here
break;
}
And this is a switch statement that do different things based on the number that randomly gets chosen.

Categories