How to optimize a lot of switch cases? - java

How could I optimize having a lot of switch cases? Is there some other method to do what I'm attempting to do?
I have a time slider and this slider updates a variable currentTime with the value (1-24) where the current slider is and calls the updateTime() method. In this method I have switch cases for 1 - 24 (only 3 in this example). Instead of making 24 switch cases, could I do this in a much simpler way?
private void updateTime() {
switch (currentTime) {
case 1:
hourlyData = weatherAPI.HourlyReport(1);
setHourlyData();
break;
case 2:
hourlyData = weatherAPI.HourlyReport(2);
setHourlyData();
break;
...
case 24:
hourlyData = weatherAPI.HourlyReport(24);
setHourlyData();
break;
default:
System.out.println("Oops");
break;
}
}
--
public Map HourlyReport(int hour) {
Hourly hourly = new Hourly(fio);
//In case there is no hourly data available
if (hourly.hours() < 0) {
System.out.println("No hourly data.");
} else {
hourlyData.put("Temp", hourly.getHour(hour).temperature()); // Temperature
hourlyData.put("TempFeel", hourly.getHour(hour).apparentTemperature()); // Feel Temperature
hourlyData.put("Humidity", hourly.getHour(hour).humidity()); // Humidity
hourlyData.put("WindSpeed", hourly.getHour(hour).windSpeed()); // Wind Speed
hourlyData.put("Precip", hourly.getHour(hour).precipProbability()); // Precipitation
hourlyData.put("TimeStamp", hourly.getHour(hour).time());// TimeStamp
}
return hourlyData;
}

The use of a switch is not justified in this case. Use a simple if
if (currentTime > 0 && currentTime < 25) {
hourlyData = weatherAPI.HourlyReport(currentTime);
setHourlyData();
} else {
System.out.println("Oops");
}

I would validate first
private void updateTime() {
if (currentTime < 1 || currentTime > 24)
throw new IllegalStateException("currentTime: " + currentTime);
hourlyData = weatherAPI.HourlyReport(currentTime);
setHourlyData();
}

You could use a simple if statement to validate currentTime's value and just pass it to weatherAPI.HourlyReport:
private void updateTime() {
if (currentTime >= 1 || currentTime <= 24) {
hourlyData = weatherAPI.HourlyReport(currentTime);
setHourlyData();
} else{
System.out.println("Oops");
}
}

private boolean isValidHour(){
if (currentTime >= 1 && currentTime <= 24)
return true;
else
return false;
}
private void updateTime() {
if(this.isValidHour())
hourlyData = weatherAPI.HourlyReport(currentTime);
else
System.out.println("Oops");
}

Related

Why does my if-chain not stop? [duplicate]

This question already has answers here:
If statement seems to be skipping to else
(5 answers)
Closed 5 years ago.
I was running a program with my students today and we came to a method that asked them to create conditional statements that prompts the user on the day of week after an input of 1 - 7 which correspond to Sunday to Saturday.
A student came up with the code below which prints out "Thursday", but it also prints out the else statement. I cannot figure out why it does not stop at d == 5. But when I changed the method to return a String and had each if statement return a String like "Sunday" it worked. The code is below. Why does the program not stop for the void method, but stop for the String method?
public static void dayOfWeek(int d) //This did not stop at d == 5.
{
if (d == 1)
{
System.out.println("Sunday");
}
if (d == 2)
{
System.out.println("Monday");
}
if (d == 3)
{
System.out.println("Tuesday");
}
if (d == 4)
{
System.out.println("Wednesday");
}
if (d == 5)
{
System.out.println("Thursday");
}
if (d == 6)
{
System.out.println("Friday");
}
if (d == 7)
{
System.out.println("Saturday");
}
else
{
System.out.println("Oops! Number must be between 1 and 7");
}
}
public static String dayOfWeek(int d) //This worked at d == 5.
{
if (d == 1)
{
return "Sunday";
}
if (d == 2)
{
return "Monday";
}
if (d == 3)
{
return "Tuesday";
}
if (d == 4)
{
return "Wednesday";
}
if (d == 5)
{
return "Thursday";
}
if (d == 6)
{
return "Friday";
}
if (d == 7)
{
return "Saturday";
}
else
{
return "Oops! Number must be between 1 and 7";
}
}
The point is that there is a difference between an else if and and if when used in consecutive conditionals. In your situation
if (a) { .. }
if (b) { .. }
else { .. }
the if (a) conditional is not related in any way to if (b). Both conditions are evaluated independently and their body executed accordingly. So the else condition is attached to the second conditional only and will be executed when b is false regardless of what's been executed before.
In any case you'd better use a String[] for that situation, eg:
private static final String[] days = { "Sunday", "Monday" ... };
public static String dayOfWeek(int d) {
if (d >= 1 && d <= 7)
return days[d-1];
else
throw new IllegalArgumentException("Day of the week out of bounds!");
}

How to get day of month in 20th format in java? [duplicate]

This question already has answers here:
How do you format the day of the month to say "11th", "21st" or "23rd" (ordinal indicator)?
(23 answers)
Closed 6 years ago.
I need to get the day of month ends with th or st e.g 20th, 21st.
Is it possible to achieve it java date time format? Any kind of help will be highly appreciated. Thanks
I think this can do what you want:
public class Base {
public static void main(String[] args) {
for (int i = 1; i < 31; i++) {
System.out.println(i + getOrdinalFor(i));
}
}
public static String getOrdinalFor(int value) {
int tenRemainder = value % 10;
if (value == 11 || value == 12 || value == 13) {
return "th";
}
switch (tenRemainder) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
}
check this first where you are using.
if(value <=30){
getOrdinalFor(value)
}else{
return "st";
}
here is your core logic
public static String getOrdinalFor(int value) {
int tenRemainder = value % 20;
switch (tenRemainder) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}

How to make a sleep thread in For loop?

I'm working on a card game app and i finished the basic stuff and now i'm trying to make it look professional.
the first thing I want to do is the effect of the distribution of cards,
i want to make a shuffle card effect.
when a card is given to a player, I want at least 500 milliseconds difference to the next card that will be distributed to him.
ideas?
this is a part from my code..
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
// MakeTheCardPause();
}
SentTheLinkedList();
}
MakeTheCardPause() is the problem...
private void MakeTheCardPause() {
Thread Timer = new Thread()
{
public void run()
{
try{
sleep(1000);
}catch(InterruptedException e)
{
e.printStackTrace();
}finally
{
//do something...
}
}
};
Timer.start();
}
thanks!
Many ways you can do this. Thread.sleep(500) is the way was you suggested but it is not what I would recommend. Here are two alternatives
Message Handler
An example
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case shuffle:
// Do something
break;
case doneShuffle:
//Do something
}
}
};
Asynch Tasks
Here is an example:
private class shuffleCards extends AsyncTask<Card, Integer, Long> {
protected Long doInBackground(Card card) {
//Do something
//shuffle deck
// Escape early if cancel() is called
if (isCancelled()) break;
}
return deck;
}
protected void onProgressUpdate(Integer... progress) {
//Number of shuffled cards??
}
protected void onPostExecute(Long result) {
//Show card
}
}
Remember this is just a background task to display results. Your main thread will be handling the actual card values and handing them over to the Asynch task.
Good Luck
What about this? You need to have the sleep in the working thread, your code above is creating a new thread and telling it to sleep, which has no noticeable effect to the user.
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
long sleepMax = 1000L;
Random r = new Random();
long delay = (long) (r.nextDouble() * range);
Thread.sleep(delay);
}
SentTheLinkedList();
}

Countdown timer with GUI using SwingWorker - not updating properly

i'm trying to make a countdown timer using swingworker, problem is when seconds get to zero, programs sets them back to 60 and deducts one.I did make the program without GUI and it works just perfect, but using swingworker my timer looks like this
1: 0: 2
1: 0: 1
0: 59: 60
which is kinda wrong and should be
1: 0: 1
1: 0: 0
0: 59: 59
Both of my class lie on the same logic.I guess it has something to do with sending the whole Time object to the 'process' but i just can't explain it to myself.
doInBackground() method :
protected Void doInBackground() throws Exception {
Integer hours = Integer.parseInt(hoursField.getText());
Integer minutes = Integer.parseInt(minutesField.getText());
Integer seconds = Integer.parseInt(secondsField.getText());
Time time = new Time(hours, minutes, seconds);
if(minutes < 59 & seconds < 59) {
if(hours >=0 & minutes >=0 & seconds >=0) {
boolean count = true;
while(count) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
Logger.getLogger(Chronometer.class.getName()).log(Level.SEVERE, null, e);
}
time.setSeconds(time.getSeconds() - 1);
publish(time);
if(time.getHours() == 0 & time.getMinutes() == 0 & time.getSeconds() == 0) {
count = false;
}
if(time.getSeconds() == 0) {
time.setSeconds(60);
if(time.getMinutes() != 0) {
time.setMinutes((time.getMinutes() - 1));
}else if(time.getMinutes() == 0) {
time.setHours((time.getHours() - 1));
if(time.getHours() >= 0) {
time.setMinutes(59);
}
if(time.getHours() < 0) {
time.setHours(0);
}
}
}
}
}else {
System.exit(0);
}
}
return null;
}
And this is the simple java class that works on the same logic :
boolean count = true;
while(count) {
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
seconds--;
System.out.println(hours + ": " + minutes + ": " + seconds);
if(hours == 0 & minutes == 0 & seconds == 0) {
count = false;
}
if(seconds == 0) {
seconds = 60;
if(minutes != 0){
minutes--;
}else if(minutes == 0) {
hours--;
if(hours >=0){
minutes = 59;
}
if(hours < 0) {
hours = 0;
}
}
}
}
If anyone could point me my mistake, i'd be very grateful.
Thanks
Adding process method
public void process(List<Time> time) {
for(Time t : time) {
showField.setText(String.valueOf(t.getHours()) + ": " + String.valueOf(t.getMinutes())+ ": " + String.valueOf(t.getSeconds()));
}
}
your line
if(time.getSeconds() == 0) time.setSeconds(60);
needs to be
if(time.getSeconds() == 0) time.setSeconds(59);
And invert this tow lines:
time.setSeconds(time.getSeconds() - 1);
publish(time);
like this:
publish(time);
time.setSeconds(time.getSeconds() - 1);
The deduction is correct but it's not showing the result because when seconds reaches cero the conditional it's executed, not showing the intermediate time.
Change this line:
if(time.getSeconds() == 0)
for this one:
if(time.getSeconds() < 0)
And this:
if(time.getHours() == 0 & time.getMinutes() == 0 & time.getSeconds() == 0)
if(time.getHours() == 0 & time.getMinutes() == 0 & time.getSeconds() < 0)
I did not dig at your logic, but you can achieve the same using Calendar which looks more simple.
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, hours);
c.set(Calendar.MINUTE, minutes);
c.set(Calendar.SECOND, seconds);
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date d = c.getTime();
System.out.println(format.format(d));
while(count) {
c.set(Calendar.SECOND, c.get(Calendar.SECOND)-1); //decrement 1 second at a time
d = c.getTime();
System.out.println(format.format(d));
Thread.sleep(1000); //Pause for a second between each print
}
I have used SimpleDateFormat("HH:mm:ss") for simplicity. If you need different fields of time, then you can use Calendar.get(..) method to get the same

java switch case question

public String sizeOfSupermarket() {
String size;
switch (this.numberOfProducts) {
case (this.numberOfProducts > 5000):
size = "Large";
break;
case (this.numberOfProducts > 2000 && this.numberOfProducts < 5000):
size = "Medium";
break;
case (this.numberOfProducts < 2000):
size = "Small";
break;
}
return size;
}
the above is wrong, how to write the compare statement in case statement?
You can use a derived value, in this case look at the number of thousands.
public String sizeOfSupermarket() {
switch (this.numberOfProducts/1000) {
case 0: case 1: return "Small";
case 2: case 3: case 4: return "Medium";
default: return "Large";
}
}
Note: you have a bug in your code such that if the numberOfProducts is exactly 2000 or 5000, it will return null (assuming it compiled)
You can't use expressions in case statements. The condition is evaluated by the switch statement, and the case statements check if the result matches.
To do what you are trying to do, you will have to use a series of if and else if statements:
if(this.numberOfProducts > 5000) {
size = "Large";
}
else if(this.numberOfProducts > 2000 && this.numberOfProducts < 5000) {
size = "Medium";
}
else {
size = "Small";
}
if (numberOfProducts >= 5000)
size = "Large";
else if (numberOfProducts >= 2000)
size = "Medium";
else
size = "Small";
You cannot use switch to test for boolean expressions. You need to use if.
You can use switch if you want to check if a variable has one certain value, i.e.:
public String sizeOfSupermarket() {
String size;
switch (this.numberOfProducts) {
case 5000:
size = "Large";
break;
case 2000:
size = "Medium";
break;
case 100):
size = "Small";
break;
}
return size;
}
Java 1.6 does not support a conditional switch statement, your best bet would be to use the if then else control structure
No way. By definition switch/case is based on enumerated types only (int, boolean, long, enum) in all C-like languages I know.
So you have to use if/else structure here:
public String sizeOfSupermarket() {
String size;
if (this.numberOfProducts > 5000) {
size = "Large";
} else if (this.numberOfProducts > 2000 && this.numberOfProducts < 5000) {
size = "Medium";
} else (this.numberOfProducts < 2000) {
size = "Small";
}
return size;
}

Categories

Resources