Selection and Iteration
The biggest unit on the exam. Programs make decisions with booleans and if-statements, and repeat work with loops. Master these and you've mastered a quarter of the test.
2.1 Boolean Expressions
A boolean expression evaluates to true or false. The most common boolean expressions use relational operators:
| Operator | Meaning | Example (x = 5) | Result |
== | equal to | x == 5 | true |
!= | not equal to | x != 3 | true |
> | greater than | x > 5 | false |
< | less than | x < 10 | true |
>= | greater or equal | x >= 5 | true |
<= | less or equal | x <= 4 | false |
🚨 = vs ==
= is assignment. == is comparison. if (x = 5) is a compile error in Java because x = 5 isn't a boolean.
✏️ Your turn — boolean variables
Given int age = 17;:
- Declare a
boolean canVote that's true when age >= 18
- Declare a
boolean isTeen that's true when age is between 13 and 19 inclusive
Print both, prefixed with canVote: and isTeen: .
Show solution
public class Main {
public static void main(String[] args) {
int age = 17;
boolean canVote = age >= 18;
boolean isTeen = age >= 13 && age <= 19;
System.out.println("canVote: " + canVote);
System.out.println("isTeen: " + isTeen);
}
}
Comparing objects vs primitives
For primitives (int, double, boolean), == compares values. For objects, == compares references — whether two variables point at the same object. Use .equals() to compare contents.
✏️ Your turn — == vs .equals()
Build two separate String objects using new String("hello") (this forces two different objects). Print a == b and a.equals(b). Predict which is true and which is false before running.
Show solution
public class Main {
public static void main(String[] args) {
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
}
}
2.2 if, if-else, and else if
Basic if
if (condition) {
// runs when condition is true
}
if-else — exactly one branch runs
if (condition) { ... }
else { ... }
else if chain — first true wins
Java tests conditions in order. As soon as one is true, that branch runs and the entire rest of the chain is skipped.
✏️ Your turn — grading chain
Given int score = 85;, write an if/else-if chain that assigns a String grade using the standard cutoffs:
- 90+ →
"A"
- 80+ →
"B"
- 70+ →
"C"
- 60+ →
"D"
- otherwise →
"F"
Print Grade: followed by the result. (Expected: Grade: B.)
Show solution
public class Main {
public static void main(String[] args) {
int score = 85;
String grade;
if (score >= 90) grade = "A";
else if (score >= 80) grade = "B";
else if (score >= 70) grade = "C";
else if (score >= 60) grade = "D";
else grade = "F";
System.out.println("Grade: " + grade);
}
}
🚨 Order matters in a chain
If you wrote if (score >= 60) first, every score from 60+ would get a D. The chain only works because each branch implicitly assumes the previous one was false.
Chain vs. independent ifs
// CHAIN — only ONE branch runs
if (x > 0) { ... }
else if (x > 10) { ... } // unreachable! x > 10 implies x > 0
// INDEPENDENT — multiple can run
if (x > 0) { ... }
if (x > 10) { ... } // both run when x is 11+
2.3 Compound Boolean Expressions
Combine booleans with logical operators:
&& — AND: true only if both sides are true
|| — OR: true if at least one side is true
! — NOT: flips true/false
Truth tables
| A | B | A && B | A || B | !A |
| T | T | T | T | F |
| T | F | F | T | F |
| F | T | F | T | T |
| F | F | F | F | T |
Short-circuit evaluation — CRUCIAL
Java evaluates left to right and stops as soon as the answer is known.
false && anything → false, right side never evaluated
true || anything → true, right side never evaluated
💡 Short-circuit saves your code
This is why if (s != null && s.length() > 0) works — if s is null, the second part never runs, so no NullPointerException.
✏️ Your turn — short-circuit in action
With int x = 0;, write an if that checks x != 0 && 10 / x > 1. Note that you'd get a division-by-zero crash if Java evaluated both sides, but short-circuit saves you. After the if, print Survived!.
Then write a second if using || that checks true || (1 / 0 == 0) — again, short-circuit prevents the crash. Print Short-circuit on || too.
Show solution
public class Main {
public static void main(String[] args) {
int x = 0;
if (x != 0 && 10 / x > 1) {
System.out.println("won't print");
}
System.out.println("Survived!");
if (true || (1 / 0 == 0)) {
System.out.println("Short-circuit on || too");
}
}
}
2.4 Equivalent Expressions & De Morgan's Laws
📘 De Morgan's Laws
!(A && B) is equivalent to !A || !B
!(A || B) is equivalent to !A && !B
In plain English: distribute the ! across both operands and flip the connective (AND ↔ OR).
Negating relational operators
!(x > 5) ≡ x <= 5
!(x == 5) ≡ x != 5
!(x >= 5) ≡ x < 5
✏️ Your turn — De Morgan
With int a = 7, b = 3;:
- Declare
boolean p equal to !(a > 5 && b < 5)
- Declare
boolean q equal to its De Morgan equivalent: a <= 5 || b >= 5
- Print
p + " " + q — both should be false.
Show solution
public class Main {
public static void main(String[] args) {
int a = 7, b = 3;
boolean p = !(a > 5 && b < 5);
boolean q = (a <= 5 || b >= 5);
System.out.println(p + " " + q); // false false
}
}
Which is equivalent to !(a >= 5 && b < 10)?
A a < 5 && b >= 10
B a < 5 || b >= 10
C a <= 5 || b > 10
D a >= 5 || b < 10
2.5 while Loops
A while loop repeats a block as long as a condition is true. Condition is checked before each iteration.
while (condition) {
// body
}
The three parts of every loop
- Initialization — set up the loop variable before the loop
- Condition — when to keep looping
- Update — change the variable inside the loop
✏️ Your turn — first while loop
Use a while loop to print i = 0 through i = 4 on separate lines. After the loop, print After loop: i = 5 (notice i is still in scope because you declared it outside).
Show solution
public class Main {
public static void main(String[] args) {
int i = 0;
while (i < 5) {
System.out.println("i = " + i);
i++;
}
System.out.println("After loop: i = " + i); // 5
}
}
🚨 Infinite loops
Forget the update? Loop runs forever. Always check your loop variable is changing toward the exit condition.
Sentinel pattern — loop until a flag value
int n = 1, sum = 0;
while (n != 0) {
sum += n;
// ... fetch next n from somewhere
}
2.6 for Loops
A for loop packages initialization, condition, and update into one line. Use it when you know how many times to loop.
for (initialization; condition; update) {
// body
}
✏️ Your turn — two for loops
Using System.out.print (no newline) and a single println() in between:
- Print
1 2 3 4 5 6 7 8 9 10 on one line
- Then print the even numbers from
20 down to 0, space-separated: 20 18 16 14 12 10 8 6 4 2 0
Use two for loops — one counting up, one counting down by 2.
Show solution
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 20; i >= 0; i -= 2) {
System.out.print(i + " ");
}
}
}
for vs while — equivalent
// for loop
for (int i = 0; i < 10; i++) { ... }
// equivalent while loop
int i = 0;
while (i < 10) {
...
i++;
}
📘 Scope of loop variable
A variable declared in the for header only exists inside the loop. If you need it afterward, declare it before the loop and use a while.
2.7 Developing Algorithms with Strings
String-processing problems are AP exam favorites. Most boil down to: loop over each character with index i and check or build with substring(i, i+1).
Classic: count occurrences of a letter
✏️ Your turn — countLetter
Write a static method countLetter(String s, String target) that returns the number of times target (a 1-character string) appears in s. Use substring(i, i+1) and .equals(target).
Test from main with:
countLetter("mississippi", "s") → 4
countLetter("mississippi", "i") → 4
countLetter("banana", "a") → 3
Show solution
public static int countLetter(String s, String target) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (s.substring(i, i + 1).equals(target)) {
count++;
}
}
return count;
}
Classic: reverse a string
✏️ Your turn — reverse
Write a static method reverse(String s) that returns s backwards. Build a result String by looping from the last index down to 0, appending each character with substring(i, i+1).
Test: reverse("hello") → olleh, reverse("abcdef") → fedcba.
Show solution
public static String reverse(String s) {
String result = "";
for (int i = s.length() - 1; i >= 0; i--) {
result += s.substring(i, i + 1);
}
return result;
}
Classic: contains a substring
✏️ Your turn — contains
Write a static method contains(String haystack, String needle) that returns true if needle appears anywhere in haystack. Loop i from 0 to haystack.length() - needle.length() inclusive, and at each position check haystack.substring(i, i + needle.length()).equals(needle).
Test: contains("hello world", "world") → true, contains("hello world", "xyz") → false.
Show solution
public static boolean contains(String haystack, String needle) {
for (int i = 0; i <= haystack.length() - needle.length(); i++) {
if (haystack.substring(i, i + needle.length()).equals(needle)) {
return true;
}
}
return false;
}
💡 Loop-bound trick
When looking for substrings of length k, loop i from 0 to length() - k inclusive. Past that causes IndexOutOfBounds.
2.8 Nested Iteration & Code Analysis
A loop inside a loop. The inner loop runs completely for each outer iteration.
Classic: multiplication table
✏️ Your turn — 5×5 times table
Use two nested for-loops (rows 1-5, cols 1-5) and System.out.printf("%4d", row * col) to print a 5×5 multiplication table. println() after each row.
Show solution
public class Main {
public static void main(String[] args) {
for (int row = 1; row <= 5; row++) {
for (int col = 1; col <= 5; col++) {
System.out.printf("%4d", row * col);
}
System.out.println();
}
}
}
Classic: triangle of stars
✏️ Your turn — star triangle
With int n = 5;, print a triangle so row r contains r stars separated by spaces:
*
* *
* * *
* * * *
* * * * *
Use nested for-loops. Outer loop iterates rows, inner loop prints row stars.
Show solution
public class Main {
public static void main(String[] args) {
int n = 5;
for (int row = 1; row <= n; row++) {
for (int col = 1; col <= row; col++) {
System.out.print("* ");
}
System.out.println();
}
}
}
Counting iterations precisely
For for (int i = a; i < b; i += step), iterations ≈ (b - a) / step.
for (int i = 0; i < 10; i++) → 10 iterations
for (int i = 0; i <= 10; i++) → 11 iterations
for (int i = 1; i <= 10; i += 2) → 5 iterations
Informal run-time sense
- One loop over N items → O(N)
- Two nested loops, both N → O(N²)
- Halving each step (binary search) → O(log N)
Tracing nested loops by hand
✏️ Your turn — predict, then verify
Before running: by hand, count how many times total++ executes when i goes from 1 to 4 and j goes from i to 4. Write your guess down.
Then write the code below and run it to verify. (Expected: 10.)
Show solution
public class Main {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 4; i++) {
for (int j = i; j <= 4; j++) {
total++;
}
}
System.out.println(total); // 4 + 3 + 2 + 1 = 10
}
}
🎯 Unit 2 Review Quiz
1. How many times does this loop body execute?
for (int i = 3; i < 12; i += 2) { ... }
2. What is total after this code?
int total = 0;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= i; j++)
total += j;
3. After this code, what is x?
int x = 10;
if (x > 5) x = 20;
else if (x > 0) x = 30;
else x = 40;
4. Which is equivalent to !(x > 5) || (y == 10) when x = 3, y = 5?
A true
B false
C Compile error
D Cannot determine