Skip to main content

Must-know sheet

Computer Science A must-know sheet

The Java rules, standard algorithms and free-response habits to know cold for AP Computer Science A, organized by unit. The course and exam changed in the 2025 update, so the first section lists what's new. The real exam gives you the Java Quick Reference, a list of the library methods you can use, so this sheet covers what it leaves out: how those methods behave at the edges, the patterns you'll trace and write, and how free response is scored.

Showing all 15 sections.

New since the 2025 course update

Units 1, 2, 3, 4

10 units became 4
The course was rebuilt for 2025–26. Roughly, Unit 1 is the old Units 1 and 2, Unit 2 is the old Units 3 and 4, Unit 3 is the old Unit 5, and Unit 4 is the old Units 6, 7, 8 and 10. Older books and videos use the old unit numbers, but most of the Java is the same.
Inheritance is gone
The old Unit 9 was cut, so you won't write extends, super or subclasses. Every class you write on the exam stands on its own.
New topics: data sets (4.2) and text files (4.6)
You now read data from a text file with File and Scanner (and add throws IOException to the method header), and turn a line of text into values with split, Integer.parseInt and Double.parseDouble. All of these are new to the Java Quick Reference; see the text files section below.
4 answer choices, typed free response
Multiple choice now has 42 questions with 4 choices (A–D), instead of 40 with 5, and counts for 55% of your score instead of half. The exam has been fully digital in Bluebook since May 2025, so you type your free-response code. Nothing compiles it, so readers go by exactly what you typed.
Free-response questions have fewer points, and Question 3 is ArrayList only
Every question used to be worth 9 points, and Question 3 could use an array or an ArrayList. Now Question 1 (Methods and Control Structures) is 7, Question 2 (Class Design) is 7, Question 3 (Data Analysis with ArrayList) is 5 and Question 4 (2D Array) is 6. Part B of Question 1 always needs String methods.
No more penalty points
Free response used to take a point off for certain mistakes, like using [] on an ArrayList. The 2026 scoring guidelines have no penalties: most of those mistakes now cost you the algorithm point instead, and a few, like a local variable you never declared, are simply ignored (see the last section).

The exam and what you're given

Units 1, 2, 3, 4

Multiple choice: 42 questions in 90 minutes, 55% of your score
Every question has 4 choices (A–D), and there's no penalty for guessing, so answer them all. Most of them have you trace code: what it prints or returns, which version works, or why one fails.
Free response: 4 questions in 90 minutes, 45% of your score
You type Java in Bluebook. Question 1, Methods and Control Structures, is 7 points (Part A 4, Part B 3); Question 2, Class Design, is 7; Question 3, Data Analysis with ArrayList, is 5; Question 4, 2D Array, is 6. That's about 22 minutes each, so give the 7-point questions a little more.
The Java Quick Reference is provided
It lists the String, Integer, Double, Math, ArrayList, File, Scanner and Object methods you can use, with a one-line description of each. You don't need to memorize headers, but you do need the edge cases and patterns on this sheet, which it doesn't spell out. No calculator is allowed.
Unit weights on the multiple choice
Unit 1 Using Objects and Methods 15–25%, Unit 2 Selection and Iteration 25–35%, Unit 3 Class Creation 10–18%, Unit 4 Data Collections 30–40%. Free response covers every unit: Question 1 uses Units 1 and 2 (calling methods, String methods, loops and ifs), Question 2 is Unit 3, and Questions 3 and 4 are Unit 4.
What the exam leaves out
The types char, long, float, short and byte; ++x and x++ inside a bigger expression; a = b = 4; keyboard input; writing your own subclasses or overriding toString or equals; writing recursive methods (you only trace them); 2D arrays with rows of different lengths; and any search or sort besides linear, binary, selection, insertion and merge. Since char is out, the exam gets one letter with substring(i, i + 1), not charAt.
You may write any valid Java
Free-response answers can use any correct Java, but staying within the Quick Reference is safest: everything you need is there, and readers know it well.

Types, arithmetic and casting

Unit 1

int, double and boolean
The only primitive types on the exam. Everything else (String, arrays, ArrayList and the classes you write) is a reference type: its variable holds a reference to an object, or null.
int / int drops the remainder
7 / 2 is 3, and -7 / 2 is -3: it cuts off the decimal part, it never rounds. If either side is a double you get the full answer, so 7 / 2.0 is 3.5.
When the division happens matters
(double) (7 / 2) is 3.0, because the int division happens first. (double) 7 / 2 is 3.5, because the cast turns 7 into 7.0 before dividing. For an average, write (double) sum / count. Also, 1 / 2 * 4.0 is 0.0, since 1 / 2 is already 0.
% gives the remainder
17 % 5 is 2, 4 % 7 is 4 and 10 % 5 is 0. Use n % d == 0 to test whether d divides n, n % 2 == 0 for even, n % 10 for the last digit and n / 10 to drop the last digit. On the exam, % only appears with a left side ≥ 0 and a right side > 0.
Order of operations
*, / and % come before + and -, and operators at the same level go left to right. 2 + 3 * 4 % 5 is 4: first 3 * 4 = 12, then 12 % 5 = 2, then 2 + 2 = 4. Parentheses override all of it.
Casting to int chops off the decimals
(int) 3.99 is 3 and (int) -3.99 is -3. To round to the nearest whole number, use (int) (x + 0.5) when x ≥ 0 and (int) (x - 0.5) when x < 0. A cast applies only to the value right after it: (int) 2.5 * 2 is 4, but (int) (2.5 * 2) is 5.
int turns into double on its own, but not the other way
double d = 5; stores 5.0, and an int mixed into double math is converted first. int n = 5.0; and int r = Math.sqrt(16); don't compile; you need a cast, like (int) Math.sqrt(16).
Integer overflow
An int holds Integer.MIN_VALUE (-2147483648) through Integer.MAX_VALUE (2147483647). Going past either end wraps around with no error: Integer.MAX_VALUE + 1 equals Integer.MIN_VALUE. These constants also make handy starting values for a minimum or maximum.
double round-off
A double can't store most decimals exactly, so 0.1 + 0.2 prints 0.30000000000000004 and 0.1 + 0.2 == 0.3 is false. When you need exact answers, work in int (cents instead of dollars).
Dividing by zero
Dividing an int by the int 0 crashes the program with an ArithmeticException. It's a run-time error: the code compiles fine.
Compound assignment, ++ and --
x += 3 means x = x + 3, and -=, *=, /= and %= work the same way, so with int x = 7;, x /= 2; leaves 3. count++; adds 1 and count--; subtracts 1; on the exam they only appear as statements on their own.
A local variable needs a value before you use it
int total; total += 5; won't compile, because total was never given a starting value. Instance variables and array elements are different: they start at 0, 0.0, false or null automatically.
Three kinds of errors
A syntax (compile-time) error breaks Java's rules, so the program won't run at all, like a missing ; or a type mismatch. A run-time error crashes it while it runs, like an exception. A logic error runs fine but gives the wrong answer, like <= where you meant <.

String methods and their edge cases

Units 1, 2

Indexes run from 0 to length() - 1
In "bear", "b" is at index 0 and "r" is at index 3, and length() is 4. Going outside the string throws a StringIndexOutOfBoundsException.
substring(a, b) stops just before b
It returns the characters from index a up to but not including b, so its length is b - a: "pumpkin".substring(1, 4) is "ump". It works when 0 ≤ a ≤ b ≤ length(); anything else throws a StringIndexOutOfBoundsException.
substring(a) and the empty string
s.substring(a) runs from a to the end. s.substring(s.length()) and s.substring(2, 2) both give the empty string "" with no error, but s.substring(s.length() + 1) throws.
One letter at a time: s.substring(i, i + 1)
That's the one-letter string at index i. Loop with i from 0 while i < s.length(), and compare the letter with equals:int count = 0; for (int i = 0; i < word.length(); i++) { String letter = word.substring(i, i + 1); if ("aeiou".indexOf(letter) >= 0) { count++; } }This counts the vowels: "education" gives 5.
indexOf returns -1 when there's no match
"banana".indexOf("an") is 1 (only the first match counts), and "banana".indexOf("x") is -1. To ask "does s contain t?", test s.indexOf(t) >= 0.
Compare strings with equals, never ==
s1.equals(s2) checks whether the letters match. == checks whether both variables refer to the very same object, so two strings with the same letters can be equals but not ==.
compareTo tells you the order by its sign
a.compareTo(b) is negative if a comes first alphabetically, 0 if they're equal and positive if a comes after. "apple".compareTo("banana") < 0, and a word comes before a longer word that starts with it: "cat".compareTo("catalog") < 0. Test the sign, never an exact number.
Strings never change (they're immutable)
String methods return a new string and leave the original alone. s.substring(1); on a line by itself does nothing useful; you have to store the result, as in s = s.substring(1);.
+ joins strings, left to right
If either side of + is a string, the other side is turned into text. "1" + 2 + 3 is "123", but 1 + 2 + "3" is "33", because 1 + 2 is added first. Use parentheses: "Sum: " + (a + b). Joining an object to a string uses its toString method.
Count every place a word appears
Check each starting index where the target could fit. Note the <= in the loop condition: the last possible start is s.length() - t.length().int found = 0; for (int i = 0; i <= s.length() - t.length(); i++) { if (s.substring(i, i + t.length()).equals(t)) { found++; } }With s = "banana" and t = "an", found is 2. Overlapping matches count: "aa" appears 2 times in "aaa".
Build a reversed copy
Walk backward from the last index and add each letter to a new string, which starts as "":String reversed = ""; for (int i = s.length() - 1; i >= 0; i--) { reversed += s.substring(i, i + 1); }"stressed" becomes "desserts". Going forward instead, write reversed = s.substring(i, i + 1) + reversed;.

Methods, Math and objects

Units 1, 3

Method signature and overloading
A signature is a method's name plus its parameter types, in order. Overloaded methods share a name but have different parameter lists. Two methods that differ only in return type won't compile.
void vs. returning a value
A void method does a job and returns nothing, so you can't use it in an expression or store its result. A non-void method returns one value of its type; calling it on a line by itself throws that value away.
Static (class) vs. instance methods
Call a static method on the class: Math.sqrt(25.0). Call an instance method on an object: name.length(). Inside its own class you can drop the prefix, but a static method has no object of its own, so it can't call instance methods or use instance variables directly.
Arguments are copied (call by value)
A parameter gets a copy of the argument's value, so changing an int parameter never changes the caller's variable. With an object, the copy is of the reference: the method can change that object, and the caller sees it, but pointing the parameter at a new object doesn't affect the caller.
Math methods
Math.abs returns the same type you give it. Math.pow(2, 3) is 8.0 and Math.sqrt(16) is 4.0: both return a double, even for whole numbers. Math needs no import, and all its methods are static.
Math.random() and random whole numbers
It returns a double from 0.0 up to but not including 1.0. A random int from low to high, both included, is (int) (Math.random() * (high - low + 1)) + low. A die roll is (int) (Math.random() * 6) + 1, giving 1 to 6. Leaving out the parentheses around the multiplication casts Math.random() to 0 every time.
Creating objects with new
new Dog("Rex", 3) calls a constructor and gives back a reference to the new object. The arguments must match one constructor's parameter types, in number and order.
null and NullPointerException
A reference variable holding null points to no object. Calling a method through it, like name.length() when name is null, throws a NullPointerException. Check name != null first, and put that check on the left of &&.
Aliases
Dog b = a; copies the reference, not the dog: a and b now refer to the same object, so a change made through b shows up through a. == on objects is true only for aliases (or two nulls); use equals to compare contents.

Boolean logic and if statements

Unit 2

Relational operators
==, !=, <, <=, > and >= compare two values and give a boolean. With primitives, == compares the values; with objects, it checks whether both refer to the same object.
Order: !, then comparisons, then &&, then ||
! applies first, then &&, then ||, and comparisons like x < 5 are worked out before && and ||. So true || false && false is true, because false && false is done first. Add parentheses when in doubt.
Short-circuit evaluation
If the left side of && is false, or the left side of || is true, Java skips the right side. Use it as a guard: i < arr.length && arr[i] > 0 never reads past the end of the array, but arr[i] > 0 && i < arr.length can crash.
De Morgan's laws
!(a && b) is the same as !a || !b, and !(a || b) is the same as !a && !b. With comparisons, flip each one too: !(x > 5 && y <= 2) is x <= 5 || y > 2. Remember that !(x < y) is x >= y, not x > y.
Checking that two expressions are equivalent
They must agree for every combination of values. List them in a truth table: 4 rows for two boolean variables, 8 for three. One row where they differ is enough to show they aren't equivalent.
if, else and else if
An if runs its block only when the condition is true; with an else, exactly one of the two blocks runs. In an else if chain, Java runs only the first block whose condition is true (or the final else if none are), so check the narrowest condition first:String grade; if (score >= 90) { grade = "A"; } else if (score >= 80) { grade = "B"; } else { grade = "C or below"; }If score >= 80 came first, a 95 would get a B.
Separate ifs are not an else if chain
Separate if statements are each checked, so several can run. With x = 10, if (x > 5) then if (x > 8), each adding 1 to count, adds 2; written as if … else if, it adds only 1.
Nested if and the dangling else
An inner if is checked only when the outer condition is true. Without braces, an else belongs to the nearest if above it that doesn't already have one, whatever the indentation suggests.
Use the boolean directly
Write return count > 0; instead of an if that returns true or false, and if (done) instead of if (done == true).

Loops and counting how often code runs

Unit 2

while loops
The condition is checked before every pass. If it's false at the start the body never runs, and if nothing in the body can make it false the loop never ends (an infinite loop).
for loops
In for (init; condition; update), the init runs once, the condition is checked before every pass, and the update runs after every pass of the body. Any for loop can be rewritten as a while loop and the other way around.
How many times a for loop runs
for (int i = a; i < b; i++) runs b - a times, and i <= b makes it b - a + 1 times (when b ≥ a). for (int i = 0; i < n; i += 2) runs (n + 1) / 2 times in int math: 5 times for n = 9 or 10.
Off-by-one errors
The most common loop bug is running one pass too many or too few: i <= arr.length reads past the end and crashes, and starting at 1 skips index 0. Check the first and last pass of every loop you write.
What's left after the loop
A variable declared in a for header doesn't exist after the loop. A counter declared before a while loop keeps its last value: after int k = 0; and while (k < 5) { k += 2; }, k is 6, the first value that failed the test.
Nested loops multiply
For each pass of the outer loop, the inner loop runs all of its passes. An outer loop of n passes around an inner loop of m runs the inner body n * m times. If the inner loop is for (int j = i; j < n; j++), the body runs n + (n - 1) + … + 1 = n(n + 1) / 2 times; starting at j = i + 1 (every pair once) gives n(n - 1) / 2.
Tracing a loop
Make a table with one column per variable and one row per pass, and update it in the exact order the statements run. Write down the condition check that finally fails; that's when the loop ends.

Standard algorithms with numbers

Unit 2

Sum and average
Start the total at 0, add inside the loop, and cast before dividing so the average keeps its decimals:int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } double average = (double) sum / n;With n = 4, sum is 10 and average is 2.5; without the cast it would be 2.0.
Work through the digits of a number
n % 10 is the last digit and n / 10 drops it. Repeat while n > 0:int digitSum = 0; while (n > 0) { digitSum += n % 10; n /= 10; }For 4072 this gives 13. The loop ends with n at 0, so copy n first if you need it later. Counting digits works the same way, with count++ in place of the sum.
Divisibility and counting factors
n % d == 0 means d divides n evenly. Counting d from 1 to n where that's true counts the factors of n (12 has 6: 1, 2, 3, 4, 6 and 12).
Counting matches
Start a counter at 0 before the loop and add 1 inside an if each time the condition is met. Declaring the counter inside the loop resets it on every pass.
Minimum and maximum
Start with the first value you look at (or Integer.MAX_VALUE for a minimum and Integer.MIN_VALUE for a maximum), then replace it whenever you find something smaller or larger. Starting a maximum at 0 gives the wrong answer when every value is negative.
Finding the first one that works
To find the smallest number that meets a test, count upward in a while loop until the test passes; the loop stops at the first success. To keep going until a running total passes a target, test the total in the condition.int k = 1; while (k * k <= limit) { k++; }With limit = 50, k ends at 8, the smallest whole number whose square is more than 50.

Writing your own class

Unit 3

The parts of a class
A header, private instance variables, constructors, then methods:public class Pet { private String name; private int age; private static int count = 0; public Pet(String name, int age) { this.name = name; this.age = age; count++; } public String getName() { return name; } public void haveBirthday() { age++; } public boolean isOlderThan(Pet other) { return age > other.age; } public static int getCount() { return count; } }Each Pet has its own name and age; count is shared by all of them.
Encapsulation: instance variables are private
Only code inside the class can use private variables. Other classes work through public methods and constructors. On the exam, instance variables are always private.
Constructors
A constructor has the class's name and no return type, not even void. Its job is to give every instance variable a starting value, usually from its parameters. If you write no constructor, Java supplies an empty one with no parameters; once you write any constructor, that free one is gone, so new Pet() wouldn't compile here.
Default values
An instance variable you never set starts at 0, 0.0, false or null, depending on its type. The same defaults fill a new array.
The this keyword
Inside a constructor or instance method, this is the object the code is running on. When a parameter has the same name as an instance variable, the parameter wins inside the method (shadowing), so write this.name = name;. Plain name = name; just copies the parameter into itself, and the instance variable stays null.
Don't redeclare an instance variable
String name = n; inside a constructor makes a new local variable that disappears when the constructor ends, and the instance variable is never set. Assign it instead: name = n;.
Accessors and mutators
An accessor (getter) returns a value and changes nothing, like getName(). A mutator (setter) changes the object's state and is usually void, like haveBirthday().
Every path must return
A non-void method must return a value of its type on every path, or it won't compile. A return ends the method at once, so nothing after it on that path runs.
static means shared by the class
A static variable has one copy for the whole class (like count above, which goes up with every new Pet). static methods have no this, so they can't use instance variables or instance methods without an object.
final means it can't change
A final variable can't be changed once it has a value. Constants are usually written private static final int MAX_SIZE = 10;.
Scope
A local variable (including a parameter) exists only inside the block { } where it's declared, and it can't be marked public or private. Instance variables can be used anywhere in the class.
Objects of the same class can see each other's private data
In isOlderThan(Pet other), other.age is allowed because the code is inside Pet. In any other class you'd need an accessor.
Mutable objects passed to a constructor
If a constructor is given an array or another object that can change, storing that reference means outside code can still change it. Store a copy when the object must keep its own data.

Arrays

Unit 4

Creating an array
int[] nums = new int[5]; makes 5 zeros; a new double[] holds 0.0s, a boolean[] holds falses, and a String[] (or any object array) holds nulls. An initializer list sets the values directly: int[] nums = {3, 1, 4};. An array's size can't change after it's made.
length with no parentheses
arr.length for an array, s.length() for a String and list.size() for an ArrayList. Free-response readers ignore mix-ups between these, but in a multiple-choice "which compiles" question they matter.
Valid indexes: 0 to arr.length - 1
arr[arr.length] or arr[-1] throws an ArrayIndexOutOfBoundsException. The last element is arr[arr.length - 1].
The enhanced for loop gives you copies
In for (int x : arr), x is a copy of each element, so x = 0; doesn't change the array, and you don't get the index. Use an indexed loop to change elements or to look at neighbors. With an array of objects, calling a method on the loop variable (like p.haveBirthday()) does change that object.
Arrays are objects
int[] b = a; makes b an alias for the same array. Passing an array to a method passes the reference, so the method can change its elements and the caller sees the changes.
Maximum (or minimum)
Start at the first element, not 0, so it works even when every value is negative:int max = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } }For the minimum, flip > to <. To track where it is, save i in a second variable.
"All" and "at least one"
Return as soon as the answer is certain, and give the other answer only after the loop has checked everything:public static boolean allPositive(int[] arr) { for (int x : arr) { if (x <= 0) { return false; } } return true; }For "at least one," return true inside the loop and false after it. Putting else return true; inside the loop is a classic bug: it decides after looking at only the first element.
Consecutive pairs
Compare arr[i] with arr[i + 1], so stop at i < arr.length - 1:int rises = 0; for (int i = 0; i < arr.length - 1; i++) { if (arr[i + 1] > arr[i]) { rises++; } }For {2, 5, 4, 8, 9} there are 3 rises.
Duplicates: compare every pair once
Use nested loops with the inner index starting one past the outer one:boolean hasDuplicate = false; for (int i = 0; i < arr.length; i++) { for (int j = i + 1; j < arr.length; j++) { if (arr[i] == arr[j]) { hasDuplicate = true; } } }Starting j at 0 would compare each element with itself and always find a "duplicate." For Strings or other objects, compare with equals.
Shift or rotate
To rotate left, save the first element, move each element one place left, then put the saved one at the end:int first = arr[0]; for (int i = 0; i < arr.length - 1; i++) { arr[i] = arr[i + 1]; } arr[arr.length - 1] = first;{1, 2, 3, 4} becomes {2, 3, 4, 1}. To rotate right, save the last element and loop from the end down, so you don't overwrite values before you've moved them.
Swap and reverse
Swapping needs a temporary variable. To reverse in place, swap the ends and move inward, stopping halfway:for (int i = 0; i < arr.length / 2; i++) { int temp = arr[i]; arr[i] = arr[arr.length - 1 - i]; arr[arr.length - 1 - i] = temp; }Looping all the way to arr.length swaps everything twice and leaves the array as it started.

ArrayList

Unit 4

Making one
ArrayList<String> names = new ArrayList<String>(); makes an empty list, and you need import java.util.ArrayList;. It holds objects only, so a list of whole numbers is ArrayList<Integer>; ArrayList<int> won't compile. Its size grows and shrinks as you add and remove.
Array vs. ArrayList at a glance
Size: arr.length / list.size(). Read: arr[i] / list.get(i). Change: arr[i] = x; / list.set(i, x);. Only the list can add and remove. Using [] on a list or .get on an array won't compile.
What each method does and returns
add(obj) puts it at the end and returns true. add(i, obj) inserts at index i and shifts later elements right. set(i, obj) replaces and returns the old element. remove(i) deletes, shifts later elements left and returns the removed element. get(i) returns the element, and size() the count.
Trace: watch the indexes shift
Start with [A, B, C]. add(1, "X") gives [A, X, B, C]. set(0, "Y") returns "A" and gives [Y, X, B, C]. remove(2) returns "B" and gives [Y, X, C].
Valid indexes
get, set and remove need 0 to size() - 1. add(i, obj) also allows i = size(), which adds at the end. Anything else throws an IndexOutOfBoundsException.
remove on an ArrayList<Integer>
nums.remove(1) removes the element at index 1, not the value 1, because the Quick Reference's remove takes an index.
Wrapper classes and autoboxing
Integer and Double wrap an int or double as an object. Java converts automatically: list.add(5) stores an Integer (autoboxing), and int x = list.get(0); turns it back (unboxing). Integer.parseInt("42") is 42 and Double.parseDouble("2.5") is 2.5.
Removing while you traverse
Removing at index i shifts the next element into spot i, so a plain forward loop skips it. Loop backward instead:for (int i = words.size() - 1; i >= 0; i--) { if (words.get(i).length() < 4) { words.remove(i); } }Going forward also works if you write i--; right after words.remove(i);, or only do i++ when nothing was removed.
Never add or remove in an enhanced for
Changing a list's size inside for (String w : words) can throw a ConcurrentModificationException. Use an indexed loop whenever the size changes.
The loop condition rechecks size()
i < list.size() is checked before every pass, so it follows the list as it grows or shrinks. A size saved in a variable before the loop goes stale.
Building a new list from an old one
Make an empty list, loop through the old one, and add what you want to keep, so the original isn't changed:ArrayList<Integer> evens = new ArrayList<Integer>(); for (int n : nums) { if (n % 2 == 0) { evens.add(n); } }Some questions walk through two lists (or a list and an array) at once with the same index, or with one index for each.
Lists of objects
Chain the calls: list.get(i).getName() gets the element, then calls its method. Compare Strings inside objects with equals.

2D arrays

Unit 4

Creating one
int[][] grid = new int[3][4]; has 3 rows and 4 columns, all 0 (or null for objects). An initializer lists the rows: int[][] grid = {{1, 2, 3}, {4, 5, 6}}; has 2 rows and 3 columns. On the exam every row has the same length.
Rows first: grid[row][col]
grid.length is the number of rows and grid[0].length is the number of columns. grid[r] alone is a whole row, a 1D array. The bottom-right element is grid[grid.length - 1][grid[0].length - 1].
Row-major traversal (across each row)
The outer loop picks the row and the inner loop moves across it:int total = 0; for (int r = 0; r < grid.length; r++) { for (int c = 0; c < grid[0].length; c++) { total += grid[r][c]; } }For {{1, 2, 3}, {4, 5, 6}}, total is 21.
Column-major traversal (down each column)
Swap the loops: the outer loop is c < grid[0].length and the inner one is r < grid.length, but the access is still grid[r][c]. Mixing up the two bounds works on a square grid and crashes on any other.
One row or one column
A single row r: loop c from 0 to grid[0].length - 1 and use grid[r][c]. A single column c: loop r from 0 to grid.length - 1 and use grid[r][c]. Row and column totals usually need a fresh total for each row or column, declared inside the outer loop.
Nested enhanced for
for (int[] row : grid) gives each row as a 1D array, and for (int val : row) gives each value. As with 1D arrays, assigning to val doesn't change the grid, and you don't get the indexes.
Neighbors and edges
Before reading grid[r - 1][c], check r > 0; before grid[r + 1][c], check r < grid.length - 1 (and the same for columns). Put the bounds check on the left of && so short-circuiting protects you.
2D arrays of objects
Free response often uses a grid of objects. Elements can be null, so check grid[r][c] != null before calling a method on one, then call methods like grid[r][c].getValue().

Searching, sorting and recursion

Unit 4

Linear search
Check each element in order until you find the target or run out. It works on unsorted data and can start from either end; in a 2D array, search each row in turn.public static int find(int[] arr, int target) { for (int i = 0; i < arr.length; i++) { if (arr[i] == target) { return i; } } return -1; }It returns the first matching index, or -1 if there isn't one.
Binary search: sorted data only
Look at the middle element. If it's the target, stop; if the target is smaller, keep only the left half; if larger, only the right half. Repeat until it's found or nothing is left. It can be written with a loop or with recursion.int low = 0; int high = arr.length - 1; int index = -1; while (low <= high && index == -1) { int mid = (low + high) / 2; if (arr[mid] == target) { index = mid; } else if (arr[mid] < target) { low = mid + 1; } else { high = mid - 1; } }Searching {3, 8, 15, 21, 29, 37, 44, 50} for 37 checks index 3 (21), then 5 (37): found in 2 checks.
Why binary search is faster
Each check throws away half of what's left, so the worst case is about log₂ n checks: at most 4 for 8 elements, 10 for 1,000 and 20 for 1,000,000. Linear search may need all n. On unsorted data, binary search can miss a value that's there.
Selection sort
Each pass finds the smallest element in the unsorted part and swaps it into the next spot, where it stays for good. Sorting {5, 2, 9, 1}: after pass 1 {1, 2, 9, 5}, pass 2 {1, 2, 9, 5} (2 was already in place), pass 3 {1, 2, 5, 9}. An array of n elements needs n - 1 passes.
Insertion sort
Each pass takes the next element and shifts larger elements of the sorted part one place right to slide it in. The front part is always sorted but not final, since later elements can still go in front. Sorting {5, 2, 9, 1}: {2, 5, 9, 1}, then {2, 5, 9, 1}, then {1, 2, 5, 9}. On data that's already sorted, nothing has to shift.
Merge sort
Split the list in half again and again until every piece has one element, then merge pieces back together in order: repeatedly take the smaller of the two front elements. {38, 27, 43, 3} splits into {38, 27} and {43, 3}, which become {27, 38} and {3, 43}, which merge into {3, 27, 38, 43}. It's recursive, and it's usually much faster than selection or insertion sort on large lists.
Tracing a sort
Questions ask what the array looks like after a certain number of passes, or how many times a line runs. Write the array out after every pass, and note whether the code sorts smallest-first or largest-first.
Recursion basics: base case and recursive call
On the exam you only trace recursive methods; you never write one. A recursive method calls itself. It needs a base case that stops without calling again, and each recursive call has to move toward that base case. With no reachable base case it calls itself until the program crashes with a StackOverflowError.
Each call has its own variables
Every call gets its own copies of the parameters and local variables, the way each pass of a loop has its own value of the loop variable. Any recursive method can be rewritten with a loop, and the other way around.
Trace by writing out the calls
Write each call on its own line until you reach the base case, then fill in the return values from the bottom up:public static int mystery(int n) { if (n <= 1) { return 1; } return n * mystery(n - 2); }mystery(7) is 7 * mystery(5) = 7 * 5 * mystery(3) = 7 * 5 * 3 * mystery(1) = 7 * 5 * 3 * 1 = 105.
Printing before or after the recursive call
Code before the recursive call runs on the way down; code after it runs on the way back up, in reverse order:public static void show(int n) { if (n > 0) { show(n - 1); System.out.print(n + " "); } }show(3) prints 1 2 3. With the print before the call, it would print 3 2 1.
Recursion on strings and lists
Recursion can walk through a String, array or ArrayList one piece at a time, usually with substring(1) or an index parameter that moves forward:public static String flip(String s) { if (s.length() <= 1) { return s; } return flip(s.substring(1)) + s.substring(0, 1); }flip("abc") returns "cba".

Text files and data sets

Unit 4

Opening and reading a file
You need import java.io.File;, import java.io.IOException; and import java.util.Scanner;, and you add throws IOException to the method header, the course's way of saying what happens if the file can't be opened. Leave it out and the code won't compile. Read while hasNext() is true, then close the file:public static int sumFile(String fileName) throws IOException { Scanner input = new Scanner(new File(fileName)); int total = 0; while (input.hasNext()) { total += input.nextInt(); } input.close(); return total; }If the file can't be found, the program stops with an exception.
Scanner reading methods
next() reads the next word (up to a space or line break), nextInt(), nextDouble() and nextBoolean() read the next value as that type, and nextLine() reads the rest of the line. Asking for an int when the next item isn't one throws an InputMismatchException. Exam code never mixes nextLine() with the other methods on the same file.
split breaks a line into pieces
"Ana,90,B".split(",") gives the array {"Ana", "90", "B"}; the commas are removed. Exam code splits on plain text like "," or " "; special regular-expression characters aren't tested. Turn number pieces into numbers with Integer.parseInt or Double.parseDouble:String[] parts = line.split(","); String name = parts[0]; int score = Integer.parseInt(parts[1]);
Data sets
A data set is a collection of related data a program can analyze to answer a question. Programs usually handle one record at a time with a loop. Sketching the data in a table first makes the algorithm easier to plan.
Privacy and bias
Collecting personal data puts people's privacy at risk, so programmers should protect it. Data can be incomplete, inaccurate or biased, and a program built on it can make repeated errors that are unfair to some groups (algorithmic bias). Data gathered for one question may not answer a different one.

Free response: how it's scored

Units 1, 2, 3, 4

Points are 1-point rows
Most rows check one specific thing, like calling a given method correctly or updating a count inside a loop, and you can earn them even when other parts are wrong. One or two rows marked "(algorithm)" check that all the steps are there and fit together in the right order. Always write something for every part.
Errors readers ignore
Small slips that don't make your meaning unclear: a misspelled or wrong-case name when only one thing could be meant, a missing ;, braces or parentheses when your indentation shows the structure, mixing up length and size(), a missing public on a class or constructor header, an undeclared local variable (unless the row asks for it), private on a local variable, and extra code that has no effect.
What costs the algorithm point
Leaving out a needed step or putting steps in the wrong order; extra code that makes the answer wrong (like printing or a wrong check); using [] on an ArrayList or .get on an array; changing data you weren't asked to change, such as a parameter's array; returning a value from a void method or a constructor; and rewriting the given method header with different parameters.
Return it, don't print it
If the method returns a value, end with return. Printing the answer instead earns nothing for it and can cost the algorithm point.
Use the methods they give you
Call the methods described in the question, and in Part B the one you wrote in Part A, instead of redoing their work. There's often a row for calling them correctly, and you can assume they work as described even if your Part A didn't.
Keep the header you're given
Don't change the method's name, return type or parameters. Write only the method or class asked for.
Class Design checklist (Question 2)
Write public class Name, a private instance variable for everything an object has to remember (including running totals the example calls imply), a constructor whose parameters match the example new call, and each method with exactly the name, parameter types and return type shown in the examples.
ArrayList and 2D Array habits (Questions 3 and 4)
Use get(i) and size() for lists and grid.length and grid[0].length for grids, call methods on the elements (list.get(i).getScore()), and handle removals and edges carefully. Trace your code once with the question's example before moving on.
Typing in Bluebook
Nothing compiles or runs your code, so readers go by what you typed. Indent consistently and line up your braces, since indentation is how readers tell what's inside a loop or if when a brace is missing.