0

I have a chunk of code that needs to determine if a given integer is between a set of other integers. I'd also like to have this in a case statement so as to not have a surplus of if..else statements everywhere. Here's a bit of the code:

switch (copies) {
        case copies >= 0 && copies <= 99: copyPrice = 0.30; break;
        case copies >= 100 && copies <= 499: copyPrice = 0.28; break;
        case copies >= 500 && copies <= 749: copyPrice = 0.27; break;
        case copies >= 750 && copies <= 1000: copyPrice = 0.26; break;
        case copies > 1000: copies = 0.25; break;
    }

where copies is an integer and copyPrice is a double. I get several errors saying that it expects to receive a integer but gets a boolean instead. What is the best (or optimal) way of setting this up? Any help is greatly appreciated!

T145
  • 1,415
  • 1
  • 13
  • 33

5 Answers5

7

This line (and similar):

case copies >= 0 && copies <= 99:

Returns a compiler error since it gives a boolean but the compiler expects an int since copy is declared as int.

One way to solve this is using an array with the desired ranks, and have a switch statement for the index found:

public double calculateCopyPrice(int copies) {
    int[] range = { 99, 499, 749, 1000 };
    double copyPrice = 0;
    int index = -1;
    for (int i = 0; i < range.length; i++) {
        if (range[i] >= copies) {
            index = i;
            break;
        }
    }
    switch (index) {
        case 0: copyPrice = 0.30; break;
        case 1: copyPrice = 0.28; break;
        case 2: copyPrice = 0.27; break;
        case 3: copyPrice = 0.26; break;
        default: copyPrice = 0.25; break; 
    }
    //probably more logic here...
    return copyPrice;
}

After some tests, I've found a more flexible solution using a TreeMap<Integer, Double> which allows you to have a specie of range (what you're looking for) and ease the search by using TreeMap#ceilingEntry:

//TreeMap to store the "ranges"
TreeMap<Integer, Double> theMap = new TreeMap<Integer, Double>();
//add the data
theMap.put(99, 0.3);
theMap.put(499, 0.28);
theMap.put(749, 0.27);
theMap.put(1000, 0.26);
//the "default" value for max entries
theMap.put(Integer.MAX_VALUE, 0.25);
//testing the solution
Double ex1 = theMap.ceilingEntry(50).getValue();
Double ex2 = theMap.ceilingEntry(500).getValue();
Double ex3 = theMap.ceilingEntry(5000).getValue();
Double ex4 = theMap.ceilingEntry(100).getValue();
System.out.println(ex1);
System.out.println(ex2);
System.out.println(ex3);
System.out.println(ex4);
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Which JDK version did you use? I tested this on JDK version 1.6.0_21 (trying to keep some support for older stuff) and got a couple `symbol not found` errors. – T145 Feb 12 '14 at 14:42
  • 1
    @T145 check here: http://ideone.com/ZOaLeS (it uses Java 1.7.0_25 but should do fine on Java 6 as well. – Luiggi Mendoza Feb 12 '14 at 14:46
2

java has no native concept of "ranges", let alone support for them in case statements.

usually, when faced with this kind of logic i personally would do one of 2 things:

  1. just have a chain of if-else statements. doesnt even habe to be a chain:

    public static double calculateCopyPrice(int copies) {
       if (copies > 1000) return 0.25;
       if (copies >= 750) return 0.26;
       //etc
    }
    

    this code has no "else" branches and is just as much typing as the switch syntax you'd like. possibly even less (i only check a single bound every time)

  2. you could use an enum, say:

    public enum Division {UNDER_100, 100_to_500, ... }
    

    and then :

    Division division = categorize(copies);
    switch (division) {
       case UNDER_100:
       //etc
    }
    

    but this is serious overkill for what youre trying to do. i'd use that if this division is also useful elsewhere in your code.

radai
  • 23,949
  • 10
  • 71
  • 115
1

Switch case function must have an exact number in case. For example:

case 0:
case 1:

You're trying to use case from some value to some value and it's not implemented that way in Java. For your problem, you must use if-else statement since it's impossible to do it with switch case. Hope it helped.

msmolcic
  • 6,407
  • 8
  • 32
  • 56
1

Look the problem is very basic..

In a switch statement it allows only the following datatypes and wrapper classes Byte,short,char,int,Byte,Short,Character,Integer,enum,String..

If you are passing anything other than that will give you an error. In your case the condition which you are evaluating will give you result which is a Boolean value.

User27854
  • 824
  • 1
  • 16
  • 40
0

NavigableMap.seilingEntry() may be a good solution in many cases,
but in other cases the following may be clearer:

double getPrice(int copies){
    return copies>1000 ? 0.25
            : copies>750 ? 0.26
            : copies>500 ? 0.27
            : copies>100 ? 0.28
            : copies>0 ? 0.30
            : 0; // or check this condition first, throwing an exception
}
Nic Stray
  • 164
  • 1
  • 11