Using random numbers in switch/case statement in java - java

wanted to use a switch statement in Java, but the variable in the switch-statement (switch(variable)) should be compared to random numbers in the case-statements (case(randomNumber)). But I get an error message like that: "case expressions must be constant expressions". So does my case-statements doesn't work with random numbers? I thought that the error message means that i have to preface the variables with "final", but that didn't work either. So, are if ... else statements the only way? I hope I explained my problem well enough to understand.
(I'm just beginning with java and the whole terminology that comes with coding)
int number = 6; //some number between 0-9
int randomNumber1 = ((int)(Math.random() * 10));
int randomNumber2 = ((int)(Math.random() * 10));
int randomNumber3 = ((int)(Math.random() * 10));
switch(number)
{
case(randomNumber1):
//some code here
case(randomNumber2):
//some code here
case(randomNumber3):
//some code here
default:
//some code here
}

The reason that it is not working is because you are doing
case(variable)
When I changed this to an actual number, it started working for me. It is saying constant expression required because it wants an actual number, not a number stored in a variable.
Hope this helps

As explained, the (expression) in a case (expression): statement must be a constant.
As for if-else being the only way, another possibility (depending on what you're trying to do overall) is to use the random numbers as keys in a map, with values of objects with a method that can be executed to perform the action you want.
Interface MyAction
{
public void doMyAction() {};
}
public class Eight implements MyAction
{
public void doMyAction() { System.out.println("I'm an eight"); }
}
public class Four implements MyAction
{
public void doMyAction() { System.out.println("I'm a four"); }
}
// ...
HashMap<Integer, MyAction> actionMap = new HashMap<>();
actionMap.put(8, new Eight());
actionMap.put(4, new Four());
// ...
MyAction myAction = actionMap.get(randomNumber);
if (myAction == null) { System.out.println("Don't have one of those"); }
else { myAction.doMyAction(); }
It's hard to see what overall goal you're trying to accomplish, which may be why you're not getting more response -- people here often don't like proposing something that may turn out to be 'wrong', even for a situation that wasn't explained completely.

As seen from the error you are getting, switch can only be used with constant expressions. To achieve what you want, you can only use branching with if, else if, and else.
if(number == randomNumber1){
//some code here
} else if(number == randomNumber2){
//some code here
} else if(number == randomNumber3){
//some code here
} else {
//some code here
}

Related

Alternative to using return statement

I'm having trouble understanding what exactly the return statement does. What would be the difference in using:
public void run()
{
System.out.println(cube(5));
}
public int cube(int num)
{
int result = num*num*num;
System.out.println(result);
}
vs
public void run()
{
System.out.println(cube(5));
}
public int cube(int num)
{
return num*num*num;
}
Isn't it basically doing the same?
In your first example, the square function will print the cube of the provided number. However, if you wanted to do something more with it, like System.out.println(square(5) + 3), printing would not give you back 125 (did you mean to call it cube?) to add to the 3, it would only say "125" in the console. The return statement actually makes the function give back 125, so you can continue to work with it as a value.
Additionally, since you declared the square function as returning an int, if you do not have a return statement, then the program will fail to compile.
The return statement allows for more modular code with clear separation of concerns.
In your first example, your first System.out.println in the run() method calls another method that both calculates and then prints; therefore, the first System.out.println doesn't print anything itself, and could be simplified to just
public void run() {
square(5);
}
public void square(int num) {
System.out.println(num * num);
}
Which is nice and concise, but let's say you don't want to System.out.println every time you calculate a square, but only print if the result is divisible by 3. If you add the logic for that scenario to your square() method, it starts to exceed its responsibility. Additionally, your square() method is now only useful to that specific scenario. So the better practice would be something like this:
public void run() {
int result = square(5);
if (result % 3 == 0) {
System.out.println(result);
}
}
public int square(int num) {
return num * num;
}
Which now allows you to re-use the square() method for other scenarios, rather than just printing squares divisible by 3.
Unrelated to the code itself, but your square() method is actually calculating a cube (num*num*num) rather than a square (num*num)
The difference would be whether or not you want to do something with the product of the function. If you just want to print the result, you're good to go. If you want to store that value into a variable to use later, you'd want to return it, and you could then call a System.out.println on that variable too. I would say fin nailed it in his response. Hope this helped!

Am I returning the correct value from my method & am I writing it correctly?

I'll preface my question with the statement that I am very new to Java, so I apologise if my code is totally disgusting to read.
What I'm trying to do: I'm writing a program that takes two integers from the user, a low value and a high value, and sends both integers to two different methods. Method #1 has a simple for loop and should print out all of the numbers between the lowest number and the highest number that are multiples of 3 or 5, and Method #2 does the same except for numbers that are multiples of 3 or 5 it also checks if that number is also a multiple of 6 and, if so, it prints the number and an asterisk next to it.
What I'm having trouble with: I'm pretty stumped on what I need to return from my methods & how to return anything at all. This is the first time I've worked on a method properly (just moved up from "Hello World) and from what I can see I don't really need to return anything at all. All the code that I've put in my methods pretty much complete the program, so I thought maybe returning the integers I sent would be enough, apparently it's not. So, without further ado, here's my code.
The Error:
javac BonusQ.java
.\MethodOne.java:19: error: illegal start of type
return(int lowestRange, int highestRange);
^
.\MethodTwo.java:36: error: illegal start of type
return(int lowestRange, int highestRange);
^
The Main:
import java.util.Scanner;
public class BonusQ
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int lowestRange = 0;
int highestRange = 0;
System.out.println("Enter the lowest integer in your range");
lowestRange = scan.nextInt();
System.out.println("Enter the highest integer in your range");
highestRange = scan.nextInt();
MethodOne.NoAsterisk(lowestRange, highestRange);
MethodTwo.Asterisk(lowestRange, highestRange);
}
}
MethodOne:
public class MethodOne
{
public static int NoAsterisk(int lowestRange, int highestRange)
{
for(int i = lowestRange; i <= highestRange; i++)
{
if (i%5 == 0)
{
System.out.println(i);
}
else if (i%3 == 0)
{
System.out.println(i);
}
}
}
return(int lowestRange, int highestRange);
}
MethodTwo:
public class MethodTwo
{
public static int Asterisk(int lowestRange, int highestRange)
{
for(int i = lowestRange; i <= highestRange; i++)
{
if (i%5 == 0)
{
if (i%5 == 0 && i%6 == 0)
{
System.out.println(i + "*");
}
else
{
System.out.println(i);
}
}
else if (i%3 == 0)
{
if (i%3 == 0 && i%6 == 0)
{
System.out.println(i + "*");
}
else
{
System.out.println(i);
}
}
}
}
return(int lowestRange, int highestRange);
}
Sorry if the post is a bit beefy to read, I just find that adding my thoughts on the code might help you explain to me what's going wrong, seeing as you may not know the extent of my incompetence :)
Thanks in advance.
Ok, Classes have members.
Members are either some variables or arrays of variables
and the methods of a class.
So you got
public class MyMethod
{
public static int Asterisk(int loRange, int hiRange)
{
// Do magic let's make a sum for this example
// You enter loRange and hiRange (you defined it above)
return loRange + hiRange // Here the method returns a result
}
}
// So then....
public static void main(String [] args)
{
// WHATEVER IS IN HERE RUNS ALWAYS FIRST.
z = Asterisk(1,2); // 1 and 2 is lo and hi range values ;)
// Z has a value of 3 now because Asterisk(1,2) returns 1 + 2
}
See how this works?
Now this works because you use the static definition (meaning there must not be an instance of MyMethod created first to use the method. It's not wrong, but if you can make a program do things with class instances, you better do it that way.
You make an instance of a class, this is called an object, using a special method. This method has the exact name of the Class and constructs an instance of it.
You should study now about constructors, abstract classes etc etc.
I can't say you do it wrong or right either. It is about what the program is all about and you should study the scope for variables and methods, and the encapsulation concept of Object Oriented Programming.
Using only static methods, goes against encapsulation principle, it is possibly wrong but I can't tell for sure.
I hope this helped you and gave you a good direction to go on with your study.
PS:
To return multiple results, you should return an array of variables, not just a variable.
You can also return nothing and just have it do the job to a needed array. This FORCES you though to make this array public. (Not a good practice)
Finally if multiple value returns are needed to just print them on the console... well, just do it in the method, no need to return anything really.
You don't need to return anything, being that the methods are printing out all the values.
You can change them into void methods, for example:
public static void asterisk(int lowest, int highest) {
//loops and if statements
//no return statement!
}
The code in the methods will run and voila, you are done!
EDIT: That being said, there's a lot more than can be done to make this code more Java-like, but for now this will work.
mmmmm...you can return types, and (int lowestRange, int highestRange) its not a type. Look at the method definition
public static int Asterisk(int lowestRange, int highestRange)
the return type is declared as int, so you should return an int value. You can do something like
return lowestRange;
return 1;
with that in consideration, the error should dissapear. The question is, why do you need to return a value? From what i've read, your methods are supose to print stuff, not to return stuff...
The return statements are out of the method. You have to put them before the close method brackets.
public class MyClass{
public int sum (int a, int b){
return a + b;
} // The return have to be before this brackets
}

Simplifying a method in java

I'm trying to create a simple method which I have below:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
if (data.equals("action1")) {
// call a method on a value
}
if (data.equals("action2")) {
// call a different method on a value
}
}
This is only a small snippet (I took a lot out of my code), but essentially I want to be able to call a specific method without testing multiple lines in my for loop for which method to call.
Is there a way for me to decide what value to call by declaring a variable at the very beginning, instead of doing so many 'if statement' tests?
OK, I have an ArrayList inside my class:
private List<Value> values;
The value object has 2 fields time and speed.
Depending on the string I pass (time or speed), I want to be able to call the specific method for that field without doing multiple string comparisons on what method I passed.
For example, I want to be able to call getSpeed() or getTime() without doing a string comparison each time I want to call it.
I just want to test it once.
Another one:
enum Action {
SPEED {
public void doSomething() {
// code
}
},
TIME {
public void doSomething() {
// code
}
};
public abstract void doSomething();
}
public void analyzeWithAnalytics(Action data) {
for (int i = 0; i < VALUE; i++) {
data.doSomething();
}
}
You can have a Map which maps the names (action1, action2, ...) to classes which common parent and one method. And make call as following:
map.getClass("action1").executeMethod();
Map<String, MethodClass> theMap = new Map<>();
interface MethodClass {
executeMethod();
}
and children:
class MethodClass1 implements MethodClass{...}
class MethodClass2 implements MethodClass{...}
Your goal is not really clear from your question. Do you want to:
avoid typing the many cases?
gain code readability?
improve performance?
In case you're after performance, don't optimize prematurely! Meaning, don't assume that this will be important for performance without checking that out first (preferably by profiling). Instead focus on readability and perhaps laziness. ;)
Anyway, you can avoid the many tests inside by simply checking data outside of the loop. But than you'd have to copy/paste the loop code several times. Doesn't make the method more beautiful...
I would also recommend using case instead of if. It improves readability a lot and also gives you a little performance. Especially since your original code didn't use if - elseif - ... which means all conditions are checked even after the first was true.
Do I get this right? data will not be changed in the loop? Then do this:
public void analyzeWithAnalytics(String data) {
if (data.equals("action1")) {
for (int i = 0; i < VALUE; i++) {
// call a method on a value
}
} else if (data.equals("action2")) {
for (int i = 0; i < VALUE; i++) {
// call a different method on a value
}
}
}
You can also switch on strings (Java 7) if you don't like ìf...
You could try something like this, it would reduce the amount of typing for sure:
public void analyzeWithAnalytics(String data) {
for (int i = 0; i < VALUE; i++) {
switch(data) {
case "action1": doSomething(); break;
case "action2": doSomething(); break;
}
}
}

Switch on EnumSet

The old way, if we wanted to switch on some complicated bitmask, we could easily do it like this (a random example from the top of my head just to demonstrate the issue):
private static final int MAN = 0x00000001;
private static final int WOMAN = 0x00000002;
// ...alive, hungry, blind, etc.
private static final int DEAD = 0xFF000000;
public void doStuff(int human) {
switch (human) {
case MAN | DEAD:
// do something
break;
// more common cases
}
}
Nowadays, since we use enums and EnumSets, I'd sometimes like to do a similar thing:
enum Human {
MAN, WOMAN, DEAD; // etc.
}
public void doStuff(EnumSet human) {
switch (human) {
case Human.MAN | Human.DEAD:
// do something
break;
// more common cases
}
}
which doesn't work, because we can only switch on an int, enum or String value. At this point, I realized it can't be done, even though that enum values are basically just hidden integers. But I like to dig around and the feature looks very useful, so:
private static final EnumSet<Human> DEAD_MAN = EnumSet.of(Human.MAN, Human.DEAD);
public void doStuff(EnumSet human) {
switch (human) {
case DEAD_MAN:
// do something
break;
// more common cases
}
}
Still no luck. Knowing the trick for switch on Strings and that EnumSets are actually 64-bit fields (or arrays of them), I would also try:
switch (human.hashCode()) {
case (Human.MAN.hashCode() | Human.DEAD.hashCode()):
// do something
break;
// more common cases
}
thinking that when the Human hashCode() would be properly implemented to give consistent results, it could work. Nope:
java.lang.Error: Unresolved compilation problem: case expressions must be constant expressions
Now, I wonder why there's no possibility to do this. I always thought of enums and EnumSets in Java like a proper replacement for those old-school bitfields, but here it seems that the new ways can't handle more complicated cases.
The right solution kind of sucks compared to any of the switch possibilities:
public void doStuff(EnumSet human) {
if (human.contains(Human.MAN) && human.contains(Human.DEAD)) {
// do something
} else {
// more common cases
}
}
In particular, since the introduction of switch on Strings, I believe there are at least two possible implementations of switch on EnumSets:
In the case (Human.MAN | Human.DEAD) expressions, simple use a compile-time type check and ordinal() instead of the enums themselves.
Using the same trick as for Strings.
At compile time, compute the hashCode() of the name of the enum values (and possibly something additional - the number of values in enum, the ordinal() etc. - everything is static and constant from the compile time on). Yes, this would mean to change the hashCode() either of the EnumSet class or the Enum class.
use instead of the enums themselves
Now, is there any serious obstacle I didn't take into count (I can come up with a few, all can be easily overcame) that would render this impossible to implement easily? Or am I right that this would indeed be possible, but not desirable enough for Oracle to implement it, because it is not used so often?
Also, let me state that this is a purely academic question possibly without a good answer (don't know, I wouldn't ask otherwise). I might make it community wiki if it proves to be unanswerable. However, I couldn't find an answer (or even anyone discussing it) anywhere, so here it goes.
In Java & Object Oriented world you would have class with setters and getters on an Object and you would use those
public void doStuff(Human human) {
if(human.isDead()) {
if(human.isMale()) {
// something
} else if (human.isFemale()) {
// something else
} else {
// neither
}
}
}
Note: switch is not a good idea because it only takes exact matches. e.g. case MAN | DEAD: will not match MAN | HUNGRY | DEAD unless you only want to match those who were not hungry before they died. ;)
I will see your "absolutely sufficient" benchmark and raise you another flawed benchmark which "shows" it takes a fraction of a clock cycle (in cause you are wondering, that is hard to believe)
public static void main(String... args) {
Human human = new Human();
human.setMale(true);
human.setDead(true);
for(int i=0;i<5;i++) {
long start = System.nanoTime();
int runs = 100000000;
for(int j=0;j< runs;j++)
doStuff(human);
long time = System.nanoTime() - start;
System.out.printf("The average time to doStuff was %.3f ns%n", (double) time / runs);
}
}
public static void doStuff(Human human) {
if (human.isDead()) {
if (human.isMale()) {
// something
} else if (human.isFemale()) {
// something else
} else {
// neither
}
}
}
static class Human {
private boolean dead;
private boolean male;
private boolean female;
public boolean isDead() {
return dead;
}
public boolean isMale() {
return male;
}
public boolean isFemale() {
return female;
}
public void setDead(boolean dead) {
this.dead = dead;
}
public void setMale(boolean male) {
this.male = male;
}
public void setFemale(boolean female) {
this.female = female;
}
}
prints
The average time to doStuff was 0.031 ns
The average time to doStuff was 0.026 ns
The average time to doStuff was 0.000 ns
The average time to doStuff was 0.000 ns
The average time to doStuff was 0.000 ns
Thats 0.1 clock cycles on my machine, before it is optimised away completely.
How about using Set methods of EnumSet.
private static final EnumSet<Human> DEAD_MAN =
EnumSet.of(Human.MAN, Human.DEAD);
public void doStuff(EnumSet human) {
if ( human.containsAll( DEAD_MAN ) )
{
// do something
break;
}
else
{
// more common cases
}
}
Acutally EnumSet's implementation of Set interface methods is very efficient and underneath is the bitfield comparison that you are looking for.
Do the following (based on your example):
enum Human {
MAN, WOMAN, DEAD; // etc.
}
public void doStuff(Human human) {
switch (human) {
case MAN:
case DEAD:
// do something
break;
// more common cases
}
}
If you want EnumSet's then you can't use switch and should refactor it to if
public void doStuff(EnumSet<Human> human) {
if( human.containsAll(EnumSet.<Human>of(Human.MAN, Human.DEAD) {
// do something
}
}
latter variant will do bitwise comparison internally.

Is it possible to loop setters and getters?

I'm fairly confident that there's no way this could work, but I wanted to ask anyway just in case I'm wrong:
I've heard many times that whenever you have a certain number of lines of very similar code in one batch, you should always loop through them.
So say I have something like the following.
setPos1(getCard1());
setPos2(getCard2());
setPos3(getCard3());
setPos4(getCard4());
setPos5(getCard5());
setPos6(getCard6());
setPos7(getCard7());
setPos8(getCard8());
setPos9(getCard9());
setPos10(getCard10());
setPos11(getCard11());
setPos12(getCard12());
There is no way to cut down on lines of code as, e.g., below, right?
for (i = 0; i < 12; i++) {
setPos + i(getCard + i)());
}
I'm sure this will have been asked before somewhere, but neither Google nor SO Search turned up with a negative proof.
Thanks for quickly confirming this!
No way to do that specifically in Java without reflection, and I don't think it would be worth it. This looks more like a cue that you should refactor your getcard function to take an integer argument. Then you could loop.
This is a simple snippet that shows how to loop through the getters of a certain object to check if the returned values are null, using reflection:
for (Method m : myObj.getClass().getMethods()) {
// The getter should start with "get"
// I ignore getClass() method because it never returns null
if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
// These getters have no arguments
if (m.invoke(myObj) == null) {
// Do something
}
}
}
Like the others stated, probably it's not an elegant implementation. It's just for the sake of completeness.
You could do it via reflection, but it would be cumbersome. A better approach might be to make generic setPos() and getCard() methods into which you could pass the index of the current item.
You need to ditch the getter/setter pairs, and use a List to store your objects rather then trying to stuff everything into one God object.
Here's a contrived example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Foo {
public static class Card {
int val;
public Card(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
public static class Position {
int value;
public Position(Card card) {
this.value = card.getVal();
}
}
public static void main(String[] args) {
List<Card> cards = new ArrayList<Card>(Arrays.asList(new Card(1), new Card(2), new Card(3)));
List<Position> positions = new ArrayList<Position>();
for (Card card : cards) {
positions.add(new Position(card));
}
}
}
You can't dynamically construct a method name and then invoke it (without reflection). Even with reflection it would be a bit brittle.
One option is to lump all those operations into one method like setAllPositions and just call that method.
Alternatively, you could have an array of positions, and then just loop over the array, setting the value at each index.
Card[] cardsAtPosition = new Card[12];
and then something like
public void setCardsAtEachPosition(Card[] valuesToSet) {
// check to make sure valuesToSet has the required number of cards
for (i = 0; i < cardsAtPosition.length; i++) {
cardsAtPosition[i] = valuesToSet[i];
}
}
Reflection would be your only option for your example case.

Categories