- Chapter 4: Decision Making with Control Statements
Computers can do much more than take input and return a simple set of formatted output (like a basic calculator). They can actually decide and perform actions based on the data that’s given to them. This is the basics of algorithm development. Algorithms are sets of rules followed by computers to solve problems. Control statements are statements in Java responsible for determining if other statements get executed, based on certain conditional values.
Conditions are expressions that may be either true or false.
One of the most basic examples (and most frequently used type) of a control statement in Java is the if statement. An if statement is a basic control statement used to make decisions given a condition that is either true or false. We indicate the start of an if statement with the keyword if and follow it with the condition we are checking.
The if statement is structured as follows:
Fig. 4.1a: If Syntax
if (condition) {
//execute these actions
}
Code language: JavaScript (javascript)
The curly braces are used to group multiple statements together. While you don’t need them if you’re only executing one statement, it’s good practice to include them anyway so you don’t get into the bad habit of forgetting them down the road. If you don’t use curly braces, it will only execute the first statement following the if statement. This will be problematic if you want to execute more than one line of code in your if statement, which will probably be most of the time.
We can compare different values to one another using the equality and relational operators. These operators can check if two values are equal and then perform a certain action, or check if two values differ from one another, and perform a different action.
These will always return a boolean value of true or false.Fig. 4.1b: Table of Comparison Operators
Name | Operator | Description | Example |
---|---|---|---|
Equal to | == | Checks if two values are equal | if(x==y) |
Not equal to | != | Checks if two values are not equal | if(x!=y) |
Less than | < | Checks if the first value is less than the second | if(x<y) |
Greater than | > | Checks if first value is greater than the second | if(x>y) |
Less than or equal to | <= | Checks if first value is less than or equal to the second | if(x<=y) |
Greater than or equal to | >= | Checks if the first value is greater than or equal to the second | if(x>=y) |
Conditions can be checked at any time. Since they’re operators, they can be used similarly to the arithmetic operators discussed in the previous chapter. The following program shows using a conditional operator outside of an if statement.
Fig. 4.1c: Conditional Operator Example
int x = 5;
int y = 6;
System.out.println(x==y);
Since x is not equal to y, the code x==y
will return a value of false to the console.
2: If Statements With Equality
Fig. 4.2a: If Example
Let’s take a look at the equality operator “==”. We use two equal signs to determine if two values are equal to one another. We cannot use a single equal sign, because Java’s already using that as the assignment operator. The “!=” operator checks if two values are not equal to each other. The following lines of code check if the value of x is equal to five or not.
public class EqualityTest{
public static void main(String[] args){
int x = 5;
if(x==5){
System.out.println("x is equal to five");
}
if(x!=5){
System.out.println("x is not equal to five");
}
}
}
Code language: JavaScript (javascript)
The output of the program is “x is equal to five” because x is in fact equal to five.
x is equal to five
If you were to change x from 5 to 6 on line 3 it would output:
x is not equal to five
3: If Statements with Other Operators
Now let’s take a look at some of the other relational operators. This program will check if one value is greater than, less than, less than or equal to, or greater than or equal to another value.
Fig. 4.3a: Operators Example
public class Main {
public static void main(String[] args) {
//Initialize Variables
int a = 5;
int b = 10;
int c = 5;
//Check some values with relational operators
if(a>b){
System.out.println("a is greater than b");
}
if(a<b){
System.out.println("a is less than b");
}
if(a>c){
System.out.println("a is greater than c");
}
if(a>=c){
System.out.println("a is greater than or equal to c");
}
if(a<c){
System.out.println("a is less than c");
}
if(a<=c){
System.out.println("a is less than or equal to c");
}
}
}
Code language: JavaScript (javascript)
The console output is as follows. Note that no lines were generated for all the statements which were false.
a is less than b
a is greater than or equal to c
a is less than or equal to c
4: A Sample Program With Multiple Options
Recall the basic calculator program from the last chapter. In this example, we’ll do something similar by creating a program that asks the user to enter two values, and then either will add OR subtract the values depending on what the user wants.Fig. 4.4a: Multiple Options Calculator
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//Declare variables.
int x = 0;
int y = 0;
int option = 0;
int result = 0;
//Make scanner
Scanner userInput = new Scanner(System.in);
//Store values
System.out.println("Please enter an integer value:");
x = userInput.nextInt();
System.out.println("Now enter a second integer value:");
y = userInput.nextInt();
System.out.println("Would you like to 1) add or 2) subtract these numbers?");
option = userInput.nextInt();
userInput.close();
//Check if they want to add
if(option==1){
result = x + y;
System.out.println("The sum of " + x + " and " + y + " is: " + result);
}
//Check if they want to subtract
if(option==2){
result = x - y;
System.out.println("The difference " + x + " - " + y + " is: " + result);
}
}
}
Code language: JavaScript (javascript)
Please enter an integer value:<br>10<br>Now enter a second integer value:
5
Would you like to 1) add or 2) subtract these numbers?
1
The sum of 10 and 5 is: 15
If you run the program again and enter 2 instead of 1 for the third option, it should subtract them instead.
5: If Else & Else If
We’re going to be building upon the conditional if statements with the addition of an if-else statement. If else statements are similar to if statements, with the addition of extra sections of code that is executed if the main condition is not met. So if the first condition is not true, it will execute the code in the “else” section of the statement.
The format for an if else statement is as follows:
Fig. 4.5a: If Else Format
//The regular if statement
if(condition){
//code to be executed if the condition is true
}
else{
//code to be executed if the condition is false
}
Code language: PHP (php)
Sample Program
The following example asks the user to enter a number and checks if it’s over or under a million using an if-else statement.
4.5b: Else Over Under Million
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//Create a Scanner & ask for a number
Scanner input = new Scanner(System.in);
System.out.println("Enter a number");
double aDouble = input.nextDouble();
input.close();
//Check if it's over a million
if (aDouble>=1000000){
System.out.println("That's at least a million!");
}
else{
System.out.println("That's under a million.");
}
}
}
Code language: JavaScript (javascript)
Else If
In addition to else, we can also add else if blocks to specify additional conditional logic. They work just like the else blocks discussed above – but we add the if keyword after them to check additional things. So if the first block of code does not execute, it will execute a second block if the condition is met, and if not, it will proceed to the third else if block, fourth, fifth, and so on.
The following example checks how large a number is (if it’s a single-digit number, in the 10s, hundreds, or over a thousand).
4.5c: If Else Example
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a number.");
double num = input.nextDouble();
input.close();
//Check how big the number is
if (num < 0) {
System.out.println("You entered a negative number");
} else if (num < 10) {
System.out.println("You entered a number between 0 and 10");
} else if (num < 100) {
System.out.println("You entered a number in the 10s");
} else if (num < 1000) {
System.out.println("You entered a number in the 100s");
} else{
System.out.println("You entered a number over 1000");
}
}
}
Code language: JavaScript (javascript)
Please enter a number.
25
You entered a number in the 10s
In the above example, 25 is less than 100, but it is also less than 1000. Note that it didn’t print out “You entered a number in the 100s,” even though the number was also less than 1000. Once the first else-if block is satisfied, the following blocks are not executed, regardless of if the conditions are met.
6: Checking Multiple Conditions at Once
What if we want to check multiple conditions at the same time?
Nested If Statements
One way to do this is with the use of nested if statements. When we say nested, we simply mean one thing placed in another.
The following program checks if a number is between 99 and 1000 using nested if statements.
Fig 4.6a: Nested If Statements
int x = 200;
//Check if the number is greater than 99 but less than 1000
if (x > 99){
if (x < 1000){
System.out.println("The number is between 99 and 1000.");
}
}
Code language: JavaScript (javascript)
The number is between 99 and 1000.
The And Logic Operator
Now let’s take a look at a slightly better way to do this using just one if statement. We can achieve this by using the AND operator, which in Java is two ampersand symbols placed between two or more conditions.Fig 4.6b: And Operator Syntax
if ((condition1)&&(condition2)){
//actions to execute if both conditions are met
}
if ((condition1)&&(condition2)&&(condition3)){
//actions to execute if all three conditions are met
}
Code language: JavaScript (javascript)
The following example performs the same check as above using an and operator.Fig 4.6c: And Operator Example
int x = 200;
//Check if the number is greater than 99 but less than 1000
if ((x > 99)&&(x < 1000)){
System.out.println("The number is between 99 and 1000.");
}
Code language: JavaScript (javascript)
The number is between 99 and 1000.
The Or Logic Operator
Finally let’s talk about the OR operator, which can check if one OR another condition is met. That is, if any of the conditions next to the OR operators are met, the code will execute. So if one condition is true, but another condition is false, it will still execute the block of code. The OR operator in Java is two vertical lines ||Fig. 4.6d: OR Operator Syntax
int x = 200;
//Check if the number is over 100 or less than 10
if ((x>99)||(x<10)){
System.out.println("x is over 100 or under 10");
}
Code language: JavaScript (javascript)
Since x is greater than 99 the first condition is met, but the second condition (less than 10) is not met. The code was executed anyways.
x is over 100 or under 10
Combining All Of Them
Note that we can combine any set of nested, AND, and OR conditions.
The following example is a little chaotic, but it checks if a number is greater than 100 AND less than 1000 AND divisible by 5 – or equal to the value 4000.Fig. 4.6e: Everything Combined Example
public class Main {
public static void main(String[] args) {
/*Check if a number is greater than 100,
less than 1000, and divisible by 5, or
is equal to the number four thousand using a
combination of all we learned.
* */
int x = 555;
//Check if the number is greater than 100
if(x>100){
//Check if it's less than 1000 and divisible by 5, or equal to 4000
if (((x<1000)&&(x%5==0))||(x==4000)){
System.out.println("x is: " + x);
System.out.println("Conditions have been met!");
}
else{
System.out.println("Conditions not met.");
}
}
else{
System.out.println("Conditions not met.");
}
}
}
Code language: JavaScript (javascript)
x is: 555
Conditions have been met!
If we change line 9 to x=4000
we get…
x is: 4000
Conditions have been met!
And just to check divisibility by 5, if we change it to x=444
we get…
Conditions not met.
7: String Equality and Memory
Take a look at the following code that checks if two Strings are equal to one another:4.7a: String Equality
String aString = "test";
String bString = "test";
if(aString == bString){
System.out.println("Strings are equal");
}
else{
System.out.println("Strings are not equal");
}
Code language: JavaScript (javascript)
The output of the above code is:
Strings are equal
This makes sense, as both Strings have a value of “test.” But now consider the following program that checks if the user typed the message “test”4.7b: String Equality With Scanner
//Make Objects
Scanner input = new Scanner(System.in);
String aString = "test";
//Get Input
System.out.println("Enter the word test");
String bString = input.nextLine();
//Close Scanner
input.close();
//Check Equality
if(aString == bString){
System.out.println("Strings are equal");
}
else{
System.out.println("Strings are not equal.");
System.out.println("You should have entered: " + aString + " but you entered " + bString);
}
Code language: JavaScript (javascript)
Now let’s see what happens when we run the program and enter the word “test”
Enter the word test
test
Strings are not equal.
You should have entered: test but you entered test
Why did the first program checking if aString was equal to bString say they were equal, but the same thing with a String acquired from a Scanner did not? I assure you, I entered the word test properly. Why is it saying I didn’t?
Comparing Objects By Reference
To answer the question of what’s going on in Figure 4.6b, we need to have an understanding of how the equality operator works in Java, and how Java stores objects in memory.
When we use the == operator on objects, Java checks the reference, or location of the object in the computer’s memory, rather than the actual contents of the object.
Usually, this isn’t a problem, as Java tries to store equivalent values at a single point in memory. When Java compiles the program with String aString = "test"; String bString = "test";
in example 7a, Java is actually only creating one String object, and both identifiers are referencing the same object in memory. This saves RAM because the JVM only has to store one String in memory rather than two.
Since Java uses the equality operator == to check if objects are equal based off the memory location they reference, in the first example Figure 4.7a it returns the message “Strings are equal.”
Now let’s take another look at the second example (Figure 4.7b).
In the second example, we created aString at compile-time, but we did not assign a value to bString, as we were waiting for input from the Scanner. Therefore, Java actually created two separate objects in memory rather than just one.
Since the equality operator checks the references and finds that the references are different, Java says that the Strings are NOT equal even though they have identical contents.
Note that this can happen with other types of variables as well. It’s safe to use the == operator on primitive data types (ints, doubles, bools, etc.) – but not on objects like Strings. Recall that Strings are not a primitive data type.
So how do we check if two strings have the same contents if the == operator isn’t an option?
8: The Equals Method
The equals()
method can be used to check if the contents of one variable are equivalent to the contents of another, regardless of where each object is stored in memory.
The example below checks if two Strings are equivalent using the equals method.4.8a: String Equality
String aString = "test";
String bString = "test";
System.out.println(aString.equals(bString));
Code language: JavaScript (javascript)
true
Now let’s fix the example from Figure 7b.4.8b: String Equality With Scanner (Fixed)
//Make Objects
Scanner input = new Scanner(System.in);
String aString = "test";
//Get Input
System.out.println("Enter the word test");
String bString = input.nextLine();
//Close Scanner
input.close();
//Check Equality
if(aString.equals(bString)){
System.out.println("Strings are equal");
}
else{
System.out.println("Strings are not equal.");
System.out.println("You should have entered: " + aString + " but you entered " + bString);
}
Code language: JavaScript (javascript)
Enter the word test
test
Strings are equal
You can also check if two Strings are not equal to each other by adding an exclamation mark in front of the boolean. This is like saying “if false… do this.” The exclamation mark is the logical not operator.Fig 4.8c: If Not
if(!aString.equals(bString)){
System.out.println("Strings are not equal");
}
else{
System.out.println("Strings are equal.");
}
Code language: Java (java)
9: Switches
The last control statement we’ll be examining in this section is Switches. Switches are statements used to select one option from a series of different available options. They work with the byte, short, char, and int primitive data types. They also work with Enums, which is something we will discuss in a later section.
Switches are divided into different blocks of code known as cases, so in each “case” we do some different action. Rather than the curly braces used to section off blocks of code in our previous examples, each switch block begins with the keyword case and ends with a break statement, made using the keyword break.
Let’s dive into this and look at an example. The following switch takes an integer and prints out some of the milestones associated with early childhood development (babies).Fig. 4.9a: Baby Development Switch
//An integer representing the baby age in months
int babyAge = 3;
//Switch milestones
switch (babyAge) {
case 6: System.out.println("Baby starts to explore environment!");
break;
case 5: System.out.println("Baby can look at themselves in mirror!");
break;
case 4: System.out.println("Baby copies facial expressions!");
break;
case 3: System.out.println("Baby can track objects!");
break;
case 2: System.out.println("Baby starts smiling!");
break;
case 1: System.out.println("Baby starts learning faces!");
break;
case 0: System.out.println("Baby is Born!");
break;
}
Code language: PHP (php)
Since the int is equal to 3, the switch block for case 3: will be executed.
Baby can track objects!
The Default Section
Another section, called the default section, is executed when the other cases are not. This is similar to an else block in our previously discussed if statements.4.9b: Default Section
//An integer representing the baby age in months
int babyAge = 8;
//Switch milestones
switch (babyAge) {
case 2: System.out.println("Baby starts smiling!");
break;
case 1: System.out.println("Baby starts learning faces!");
break;
case 0: System.out.println("Baby is Born!");
break;
default: System.out.println("I don't know what babies do at this age.");
break;
}
Code language: PHP (php)
I don't know what babies do at this age.
Fall Through Switches
If we take out the break statements, we can allow the switch to fall through, which results in the switch skipping the blocks up until it reaches the appropriate case, and still executes the remaining code until it reaches a break.
To demonstrate this, in the following code, I have removed all the breaks except for the default case. This means it will print out the milestones for each age up until it gets to the section with the current age.4.9c: Baby Age Fallthrough
//An integer representing the baby age in months
int babyAge = 3;
//Switch milestones
switch (babyAge) {
case 6: System.out.println("Baby starts to explore environment!");
case 5: System.out.println("Baby can look at themselves in mirror!");
case 4: System.out.println("Baby copies facial expressions!");
case 3: System.out.println("Baby can track objects!");
case 2: System.out.println("Baby starts smiling!");
case 1: System.out.println("Baby starts learning faces!");
case 0: System.out.println("Baby is Born!");
default: break;
}
Code language: PHP (php)
Since I entered the age of 3, it will skip cases 6, 5, and 4, then start executing on the switch block with case 3. All the following blocks from 3 to default are then executed.
Baby can track objects!
Baby starts smiling!
Baby starts learning faces!
Baby is Born!
In most situations where we see fall-through switches, the break will be in the default section at the end. However, you can place the break in any of the other cases and Java will exit the switch at that point.
Also, note that I intentionally ordered this switch by age from older to younger – allowing it to fall through and display all the milestones currently achieved. If I ordered the cases from 0 to 6 instead of 6 to 0, it would have printed out the milestones coming after the baby’s current age (in other words, it would have printed milestones 3 through 6 instead of 3 through 0).
Default at Top
For our final example, we’ll take a look at switch behavior when we place the default section at the top instead of the bottom.
Take a look at the following code, which doesn’t do anything particularly important other than demonstrate a concept. What do you think the output will be if we set int x equal to five?
//create int to test
int tester = 5;
//Switch
switch (tester) {
default: System.out.println("Default");
case 1: System.out.println("One");
case 2: System.out.println("Two");
case 3: System.out.println("Three");
break;
}
Code language: PHP (php)
The output works almost the same way the last switch did. Since the int value of 5 is not in the list, it falls through and prints out everything, starting with the default block.
Default
One
Two
Three
Now let’s take a look at what happens when we set the integer to value 2. Will it print out the default block and cases 2-3? Or will it just print out cases 2-3?
//create int to test
int tester = 2;
//Switch
switch (tester) {
default: System.out.println("Default");
case 1: System.out.println("One");
case 2: System.out.println("Two");
case 3: System.out.println("Three");
break;
}
Code language: PHP (php)
In this scenario, it will skip the default block, because the number 2 exists as one of the cases. It just prints out:
Two
Three
So in other words, the default block is only used if none of the other cases match, even if placed before all other cases. It’s not a generic block that’s guaranteed to run every time.
Review Exercise: Federal Income Tax Calculator (USA)
In this review exercise, we are going to make a calculator that determines the total amount a user pays in towards federal taxes at each bracket level based on their provided annual income.
It is important to understand how tax brackets work if you do not know how they work already. In the USA taxes are based on these tax brackets. You pay the applicable taxes on your income at the rate specified in each specific bracket for that individual portion of your income. Take an example with someone making $25,000 a year. The first $9,950 is taxed at 10%. The remaining $15,050 is taxed at 12%. The entire 25,000 is not taxed at 12%. This way, someone on the border of tax brackets won’t be losing money by making more income. More income always equals more money in your pocket (as far as federal taxes go, at least).
Federal income tax in the United States for individuals is calculated according to this table.
Zero to $9950 | 10% |
$9951 to $40525 | 12% |
$40526 to $86375 | 22% |
$86376 to $164925 | 24% |
$164926 to $209425 | 32% |
$209426 to $523600 | 35% |
$523601 or more | 37% |
Assignment Instructions
Using conditional statements however you would like, create a program that calculates the amount of taxes owed at each income bracket, the total amount of the taxes they should expect to pay, and the final ratio of taxes to income expressed as a percentage. Use a Scanner to read the user input and double values to store the money (even though I said we shouldn’t use doubles for currency, in this example it’s okay, as it’s more of an estimator rather than a full-fledged banking application) There are multiple ways to go about doing this. Assume there are no deductions or tax credits to take into consideration – just go off the gross income.
Sample Output
When compiled, your program should execute something like this:
Please enter your total income for this year.
500000
Breakdown by tax bracket:
Bracket 1: $995.0
Bracket 2: $3668.8799999999997
Bracket 3: $10086.78
Bracket 4: $18851.76
Bracket 5: $14239.68
Bracket 6: $106497.65
Bracket 7: $0.0
Total Federal Taxes Owed: $154339.75
Average tax rate across all brackets:30.86795%
Suggested Steps
- Create a Scanner, get input as a double, and close the Scanner
- Determine the total amount you need to tax in each bracket
- Use a variable to keep track of the remaining income to tax after calculating each bracket
- Use conditions to check if we need to proceed to the next bracket, or stop at this one.
- If we know we won’t make it to the next bracket, we calculate the taxes for the last bracket as the remaining amount to tax multiplied by the rate.
- If we need to go to a higher bracket, we know we need to calculate taxes for the current bracket as the difference between the start and end income of the bracket multiplied by the percentage
- Calculate totals and output the results
Conclusion
In this section we discussed learned how to use control statements to make decisions in Java. We also learned about how Java stores objects in memory, and why we need to use the equals method for variables that are not primitive data types. If you didn’t know it already, you should now know how tax brackets work, and some of the stages of baby development. Haha. I hope you found this useful. In the next section you will learn about working with BigDecimals to perform precise calculations and the basics of memory management.