Java Coding Interview Pitfalls: Overflow, == and Modulo
The Java mistakes that fail coding interviews: int overflow, integer division, % with negatives, == on strings and Integers, split on a regex, recursion depth.
- Course: Java study plan
- Module: Interview idioms
- Kind: Lesson
- Reading time: 14 min
- Runtime: OpenJDK 18
What are the most common Java mistakes in coding interviews?
The most common Java mistakes in coding interviews are int overflow in sums, products and (lo + hi) / 2; integer division and % with negative numbers; comparing strings or boxed Integers with ==; string concatenation in a loop; split treating its argument as a regex; sorting an int[] on adversarial input; recursion too deep for the stack; and forgetting to flush buffered output.
Lesson
Most rejected solutions are not wrong algorithms. They are right algorithms with an int that overflowed, a / that truncated, a == that compared references, or a sort that hit its worst case. Interviewers know the list; this lesson is that list, each item with the one-line fix, organised so you can run it as a review pass over your own code before you say "done". Nothing here is new — every item was taught in an earlier module — but seeing them together is what turns knowledge into a reflex.
Arithmetic
intoverflow.a[i] * a[j]with values up to 10⁵ is 10¹⁰: overflow. Sums of 10⁵ values up to 10⁵: overflow.mid = (lo + hi) / 2withhinearInteger.MAX_VALUE: overflow — writelo + (hi - lo) / 2or(lo + hi) >>> 1. Fix:longfor anything that multiplies or accumulates;Math.addExact/multiplyExactwhen you would rather throw than be silently wrong.- Integer division.
7 / 2is3;1 / 2 * xis0. Make one operand adoublewhen you mean a fraction. Division truncates toward zero:-7 / 2is-3, not-4;Math.floorDivrounds down. %with negatives.-7 % 3is-1in Java. For a non-negative remainder (hashing, circular indexes, modular arithmetic) useMath.floorMod(-7, 3)→2, or((a % m) + m) % m.Math.abs(Integer.MIN_VALUE)isInteger.MIN_VALUE— still negative. Any "take the absolute value" on unconstrained input needslong.- Floating point equality.
0.1 + 0.2 == 0.3isfalse. Compare with a tolerance (Math.abs(a - b) < 1e-9), or avoid doubles: money inlongcents, exact fractions as numerator/denominator,BigDecimalwhen the statement demands exactness. - Casting truncates.
(int) 3.99is3;(int) -3.99is-3;(int) 1e10saturates toInteger.MAX_VALUE.Math.roundreturnslongfor adoubleargument.(int) 'a'is97and(char) ('a' + 1)is'b'—'a' + 1alone is anint,98. - Modular arithmetic under 10⁹ + 7. Reduce after every
*; multiply inlong; usefloorModafter subtraction; precompute factorials and inverses when the problem repeats them.
Strings and characters
==on strings. Useequals. The interned-literal cases that make=="work" in tests will not survive input.- Concatenation in a loop is O(n²).
StringBuilder, orString.join, orCollectors.joining. substringin a loop is O(n) each (a copy since Java 7u6). Sliding-window and palindrome problems should index into the original string or achar[].splitquirks."a,b,,".split(",")drops trailing empties ([a, b]);split(",", -1)keeps them.split(".")splits on any character — the argument is a regex;split("\\.")orsplit(Pattern.quote(".")).- Characters versus code points.
s.length()counts UTF-16 units; emoji are two.s.charAt(i) - '0'converts a digit;Character.getNumericValuehandles more.Character.isLetterversus[a-z]— decide whether the statement means ASCII. - Case.
toLowerCase()without aLocalefollows the default locale (the Turkishİproblem);toLowerCase(Locale.ROOT)in anything that must be deterministic.
Boxing and collections
==onInteger/Long. Cached to 127 and not beyond —map.get(a) == map.get(b)lies past 127.equals, or unbox toint.Arrays.asList(int[])gives aList<int[]>with one element — the array. Box first, orArrays.stream(a).boxed().toList().list.remove(int)versusremove(Object)on aList<Integer>:remove(2)removes index 2.remove(Integer.valueOf(2))for the value.- Modifying while iterating →
ConcurrentModificationException. Use the iterator'sremove,removeIf, or collect first then remove. - Mutable keys in a
HashMap/HashSet(previous lesson): unreachable entries. Arrays.sort(int[])worst case. Dual-pivot quicksort on primitives is O(n²) on adversarial input, and judges have anti-quicksort tests. Shuffle first, or sortInteger[]/aList(TimSort, guaranteed n log n), or use counting/radix when values are bounded.PriorityQueueiteration is not sorted. Onlypeek/pollgive order; to print sorted, poll repeatedly or sort separately.HashMapiteration order is arbitrary and can differ between runs and versions; never rely on it for output.TreeMaporLinkedHashMap, or sort the keys.Collections.unmodifiableListis a view over the original;List.copyOfis a snapshot.subList,Arrays.asList,keySet,valuesare views: changes propagate, and structural changes to the parent invalidatesubList.
Control flow and recursion
- Recursion depth. Java's default stack handles roughly 10⁴–2 × 10⁴ frames; a DFS on a path graph of 10⁵ nodes overflows. Convert to iteration with an explicit stack, or run the recursion in a
new Thread(null, runnable, "dfs", 1 << 26)with a bigger stack. switchfall-through in the old form; missingbreakmerges cases. Use arrow cases.- Off-by-one.
for (i = 0; i <= n; i++)with an array ofn;substring(i, j)is end-exclusive;Arrays.fill/copyOfRangeare[from, to). - Uninitialised
Integer.MIN_VALUE/MAX_VALUEsentinels when the answer can legitimately equal them; uselongsentinels or a booleanfound. - Returning inside
trywith afinallythat also returns — thefinallywins and swallows the exception. Neverreturnfromfinally.
Reading and output
Scanner.nextInt()thennextLine()returns the rest of the current line (""). Consume the newline, or use the reader template.- Forgetting
flush(), trailing debugging prints, printing with the wrong locale — the output half of the earlier lesson.
How to use this list
Before submitting, scan your code once for each group heading: arithmetic (any int that grows? any / or % with negatives?), strings (==? concatenation in a loop? split on a regex character?), collections (boxed ==? sorting a primitive array on adversarial input? iteration order?), recursion (depth?), I/O (flush?). Thirty seconds, and it catches the majority of "correct but rejected" submissions. In an interview, doing it aloud — "let me check for overflow: the sum is at most 10¹⁰, so long" — is the visible carefulness that gets people hired.
Interview angle
- "Why did
-7 % 3give-1?" Java's%takes the sign of the dividend;Math.floorModfor a non-negative result. - "Is
Integer a = 1000, b = 1000; a == btrue?" No — outside the cache;equals. - "Why is
Arrays.sort(int[])dangerous on a judge?" Quicksort worst case on crafted input; shuffle or sort objects. - "What does
\"a.b\".split(\".\")return?" An empty array —.is a regex wildcard; escape it. - "How do you avoid
StackOverflowErrorin a deep DFS?" Iterate with an explicit stack, or a thread with a larger stack.
Key takeaways
- Arithmetic:
long,floorMod/floorDiv,lo + (hi - lo) / 2, tolerance for doubles,abs(MIN_VALUE). - Strings:
equals,StringBuilder, nosubstringin loops,splitis a regex with dropped trailing empties. - Collections: boxed
==,remove(int), CME, mutable keys,Arrays.sort(int[])worst case, unorderedHashMap, views. - Recursion depth and
finallyreturns;Scannernewline;flush. - Run the list as a thirty-second review pass, out loud.
Common questions
Why does -7 % 3 return -1 in Java?
Java's % takes the sign of the dividend, so a negative left operand gives a negative remainder. Use Math.floorMod(-7, 3), which returns 2, or ((a % m) + m) % m when you need a non-negative result for hashing, circular indexes or modular arithmetic.
Is Integer a = 1000, b = 1000; a == b true in Java?
No. Autoboxing caches Integer values only from -128 to 127 by default, so two boxed 1000s are different objects and == compares their references. Use equals, or unbox to int first.
Why does split(".") return an empty array in Java?
split takes a regular expression, and . matches any character, so every character is a separator and the empty strings left over are dropped as trailing empties. Use split(Pattern.quote(".")) or an escaped dot to split on a literal full stop.
How do you avoid integer overflow when computing mid in binary search?
(lo + hi) / 2 overflows when both are near Integer.MAX_VALUE; write lo + (hi - lo) / 2 or (lo + hi) >>> 1. More generally, use long for anything that multiplies or accumulates, and Math.addExact or multiplyExact to throw instead of wrapping silently.
How do you avoid StackOverflowError in a deep DFS in Java?
Java's default stack handles roughly 10⁴ to 2 × 10⁴ frames, so a recursive DFS over a path of 10⁵ nodes overflows. Rewrite it with an explicit stack, or run the recursion in a thread created with a larger stack size, such as new Thread(null, task, "dfs", 1 << 26).
Why is Arrays.sort on an int array risky in competitive programming?
Dual-pivot quicksort on primitives is O(n²) on adversarial input, and some judges include anti-quicksort tests. Shuffle the array first, sort an Integer[] or a List (TimSort, guaranteed O(n log n)), or use counting sort when values are bounded.
Exercises
Exact arithmetic
Read an integer n and n lines a op b with long operands and op one of + - * % / (b is never 0). For +, - and * print the exact result via Math.addExact/subtractExact/multiplyExact, or overflow if it throws. For % print rem=<a % b> mod=<Math.floorMod(a, b)>; for / print div=<a / b> floor=<Math.floorDiv(a, b)>.
Example: 4 then 9223372036854775807 + 1, -7 % 3, -7 / 2, 6 * 7 →
overflow
rem=-1 mod=2
div=-3 floor=-4
42Predict, then verify
Read an integer k and k expression ids in 1..15. For each id print <id>: <value>, where the value is what Java computes for the expression — write each expression literally, do not hard-code the answers, and predict every line before running:
| id | expression | id | expression | |
|---|---|---|---|---|
| 1 | (int) 3.99 | 9 | -7 / 2 | |
| 2 | 7 / 2 | 10 | -7 % 3 | |
| 3 | 7 / 2.0 | 11 | "1" + 2 + 3 | |
| 4 | 'a' + 1 | 12 | 1 + 2 + "3" | |
| 5 | (char) ('a' + 1) | 13 | "a.b".split(".").length | |
| 6 | Integer.MAX_VALUE + 1 | 14 | "a,b,,".split(",").length | |
| 7 | Math.abs(Integer.MIN_VALUE) | 15 | Integer.valueOf(128) == Integer.valueOf(128) | |
| 8 | 0.1 + 0.2 == 0.3 |
Example: 3 then 2 3 11 →
2: 3
3: 3.5
11: 123In this module: Interview idioms
- The interview template — input, output, limits
- equals, hashCode and Comparable — the contracts that make collections work
- The pitfalls that fail interviews (this lesson)
- The collections idiom sheet
- Writing clean solutions under time pressure
- The Java theory drill — thirty questions, thirty answers
- Final checkpoint — Interview idioms
← equals, hashCode and Comparable — the contracts that make collections work · The collections idiom sheet →