Command Palette

Search for a command to run...

PHASE 16Advanced ~40 min· topic 1 of 4

Topic 16.1

Core Java Interview Questions

In one line

A bank of the Core Java questions interviewers ask most, from the JVM and Strings to HashMap internals, generics, modern Java, concurrency and garbage collection, each with an interview-grade answer and a link to the topic that teaches it.

Think of it like this

A driving test isn't a quiz about the names of car parts. The examiner watches whether you check the mirror *before* you turn, and asks "why did you slow down there?". A Java interview is the same: the interviewer wants to see that you know why things work, not only what they are called.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Contract
A rule a method must follow so that other code can rely on it, such as "equal objects must have equal hash codes".
Bucket
One slot in a HashMap's internal array. Keys whose hashes point to the same slot share the bucket.
Collision
Two different keys landing in the same bucket. The map must then compare them with equals.
Fail-fast
An iterator that throws an exception as soon as it notices the collection was changed behind its back, instead of giving wrong results.
Lazy evaluation
Work is described first and done only when a result is actually needed, as stream pipelines do.
Happens-before
The Java Memory Model's rule for when one thread is guaranteed to see what another thread wrote.
GC root
A starting point the garbage collector trusts is alive, such as a local variable on a thread's stack or a static field.
Follow-up
The next, deeper question an interviewer asks after your first answer, usually about the mechanism or a failure case.

Step by step

01Use the four-part answer shape

Definition, mechanism, example, trap. Practise it on any question. "What is autoboxing?" Definition: the compiler converts between int and Integer for you. Mechanism: Integer x = 5 compiles to Integer.valueOf(5), and int y = x compiles to x.intValue(). Example: list.add(5) on a List<Integer>. Trap: unboxing null throws NullPointerException, and Integer values outside -128 to 127 are separate objects, so == on them is unreliable.

The shape keeps you from rambling and shows the interviewer each layer of your understanding. Stop after the trap and let them choose the follow-up.

Main.javawhole filejava
Integer x = 5;        // compiled as Integer.valueOf(5)
int y = x;            // compiled as x.intValue()
Integer none = null;
int z = none;         // NullPointerException: unboxing null

02The JVM family: JDK, JRE, JVM, bytecode

javac turns .java source into .class files of bytecode, instructions for a virtual machine rather than a real CPU. The JVM loads classes (Topic 14.1), verifies them, interprets the bytecode and compiles hot methods to machine code with the JIT (Topic 14.4). The JRE is a JVM plus the standard library; the JDK is the JRE plus tools such as javac, jshell, jcmd and jlink. Since Java 11, Oracle and most vendors ship only the JDK (Topic 0.2).

Follow-ups: "Is Java compiled or interpreted?" (both: compiled to bytecode, then interpreted and JIT-compiled at run time). "Why is Java platform independent?" (bytecode is the same everywhere; each platform has its own JVM).

The JVM family: JDK, JRE, JVM, bytecodediagram
Rendering diagram…

03The equals and hashCode family

The contract (Topic 4.8): if a.equals(b) then a.hashCode() == b.hashCode(). The reverse is not required: unequal objects may share a hash code (a collision). equals must be reflexive, symmetric, transitive, consistent, and x.equals(null) must be false.

Why it matters: HashMap.get(key) first uses hashCode to pick a bucket, and only then calls equals on keys in that bucket. Override equals without hashCode and two equal keys usually land in different buckets, so the map never even compares them. The first runnable example below shows the lost key. Records (Topic 4.9) generate both methods correctly from their components.

04The HashMap family

A HashMap is an array of buckets (16 by default). put computes hash = h ^ (h >>> 16) from key.hashCode() to mix the high bits into the low bits, picks bucket hash & (length - 1), and either stores a new node there or walks the bucket comparing hash and equals, replacing the value of a matching key.

When the number of entries exceeds capacity * loadFactor (0.75 by default), the table doubles and entries are split between their old index and old index plus old capacity. Since Java 8, a bucket holding more than 8 nodes in a table of at least 64 slots is converted to a red-black tree, so even a flood of colliding keys costs O(log n) per lookup instead of O(n). One null key is allowed and lives in bucket 0. Topic 9.4 traces all of this step by step.

The HashMap familydiagram
Rendering diagram…

05The modern Java family

Know the headline features of each LTS release and be ready to write one line of each. Java 8: lambdas, streams, Optional, default methods, java.time. Java 11: var in lambda parameters, String.isBlank/strip/lines/repeat, the HttpClient, single-file java Main.java. Java 17: records, sealed classes, text blocks, pattern matching for instanceof, switch expressions. Java 21: virtual threads, record patterns, pattern matching for switch, sequenced collections. Topic 11.6 has the full map.

A common follow-up is "which feature changed how you write code most?". A good answer names one, shows before and after, and gives the reason, for example records replacing 40 lines of data-class boilerplate and removing a whole class of equals bugs.

06The concurrency and memory family

synchronized gives mutual exclusion (one thread at a time in the block) and visibility (changes made before releasing the lock are seen by the next thread to take it). volatile gives visibility and ordering for one variable but no mutual exclusion, so count++ on a volatile field is still a race (Topics 13.3 and 13.4).

For memory: each thread has its own stack of frames holding local variables and references; objects live on the shared heap; class metadata lives in Metaspace (native memory, since Java 8 replaced PermGen). The garbage collector finds live objects by tracing from GC roots, and everything unreachable is reclaimed. G1 has been the default collector since Java 9 (Topics 14.2 and 14.3).

The concurrency and memory familydiagram
Rendering diagram…

07Practise out loud, then verify

Read a question, close the page, and answer it aloud in under two minutes using the four-part shape. Then open the model answer and the linked topic and note what you missed. Run the examples below and change them until the behaviour no longer surprises you.

Interviewers often ask you to *write* a small piece of code: an equals/hashCode pair, a thread-safe counter, a stream that groups and counts. The practice tasks below are exactly those.

Try it yourself

  1. 1

    Fix the lost key

    In "equals without hashCode loses the key", add @Override public int hashCode() { return Objects.hash(x, y); } to Point. Predict the second line before you run it. It should now print bad map finds: treasure.

  2. 2

    Make the compiler stop folding

    In "String identity versus equality", declare final String part = "ja";. Predict a == e first. A final local initialised with a constant is itself a constant variable, so part + "va" is folded at compile time and the line prints true.

  3. 3

    Watch laziness

    In the stream example, delete the limit(2) call. Predict how many filter lines print now (five), and how many map lines (three). Then replace .toList() with nothing and only print "done": no filter line prints at all, because without a terminal operation the pipeline never runs.

Code & diagrams

equals without hashCode loses the key Java 16+ New tab

Point inherits Object.hashCode, so two equal Points almost always get different hashes and land in different buckets. The map never calls equals on them.

Sign in to run this example in your browser.

Expected output

equal keys?      true
bad map finds:   null
good map finds:  treasure
same hash codes: true
String identity versus equality New tab

"ja" + "va" is a compile-time constant, so javac folds it into the literal "java" and it shares the pooled object. part + "va" is computed at run time and creates a new String.

Sign in to run this example in your browser.

Expected output

a == b       true
a == c       false
a.equals(c)  true
a == d       true
a == e       false
a == "ja" + "va"  true
Fail-fast iteration and the safe ways to remove Java 9+ New tab

The for-each loop removed "bo" before the iterator noticed the change, which is why only ana and di remain after "cy" is removed. Topic 9.9 explains the modCount check behind this.

Sign in to run this example in your browser.

Expected output

for-each remove: ConcurrentModificationException
after it.remove: [ana, di]
after removeIf:  [ana]
Streams are lazy and run element by element Java 16+ New tab

Each element flows through the whole pipeline before the next one starts, and limit(2) stops the source early: 4 and 5 are never examined. Stream.toList() is Java 16.

Sign in to run this example in your browser.

Expected output

pipeline built, nothing ran yet
filter 1
map    1
filter 2
filter 3
map    3
result [10, 30]
A model answer in code: a correct equals and hashCodejava

The class is final, so no subclass can add a field and break symmetry. The fields used in equals and hashCode are final, so the hash can't change while the object sits in a HashMap.

import java.util.Objects;

public final class Isbn {
    private final String value;

    public Isbn(String value) { this.value = Objects.requireNonNull(value); }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;                 // fast path, also reflexive
        if (!(o instanceof Isbn other)) return false; // handles null and other types
        return value.equals(other.value);           // same fields as hashCode
    }

    @Override
    public int hashCode() {
        return value.hashCode();                    // equal objects, equal hashes
    }
}

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Mutate a key after putting it in a HashSet

Use a mutable key class with equals/hashCode on a field, add it to a HashSet, change the field, then call set.contains(key) and set.remove(key).

terminal
$ java Main.java
── what you'll see ──
contains after change: false
removed: false
size: 1

Break #2

Unbox a null Integer

Write Map<String, Integer> stock = new HashMap<>(); int n = stock.get("pens");.

terminal
$ java Main.java
── what you'll see ──
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null
at Main.main(Main.java:6)

Myth vs fact

Myth

Interviewers want you to recite definitions.

Fact

They want the mechanism and the trap. A definition alone is the weakest possible answer; "here is what the JVM does, and here is how it bites you" is the strongest.

Myth

If two objects have the same hashCode, they are equal.

Fact

The contract only goes one way. Unequal objects can and do share hash codes; "Aa".hashCode() and "BB".hashCode() are both 2112.

Myth

Java passes objects by reference.

Fact

Java always passes by value. For an object, the value copied is the reference, so the method can change the object but can't make the caller's variable point somewhere else (Topic 3.3).

Myth

Calling System.gc() frees memory immediately.

Fact

It is only a request. The JVM may ignore it (and does with -XX:+DisableExplicitGC). Memory is reclaimed when the collector decides to run.

Interview problem

The problem

What happens when you call map.put(key, value)?

An interviewer asks: "Walk me through exactly what happens inside a HashMap when I call put, including collisions and resizing. Then tell me what changes if two threads call put at once."

You're given

  • Cover hashing, the bucket index, collisions, equals, resizing and treeification.
  • Give the cost of each step.
  • Explain the concurrency problem and the fix.

The interviewer follows up

01

Why is the capacity always a power of two?

02

If you know you'll store 1,000 entries, how do you avoid resizes?

03

Why does ConcurrentHashMap reject null values?

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    HashMap stores the spread hash in each node, so resizing never calls hashCode again, and lookups compare the stored int before calling equals. That is why a cheap hashCode and an expensive equals still perform well.

  • ▸

    Treeification needs an ordering. For keys of the same class that implement Comparable, the tree uses compareTo; otherwise it falls back to comparing class names and then System.identityHashCode just to break ties, and lookups may search both subtrees. Implementing Comparable on keys keeps tree buckets O(log n) under heavy collisions.

  • ▸

    Since Java 9, compact strings store Latin-1 text in a byte[] with one byte per character and switch to two bytes only when needed, roughly halving the memory of most Strings. String.hashCode caches its result in a field, which is another reason immutability matters for map keys.

  • ▸

    In senior interviews the question "what happens when…" is often a hook for production stories: an unbounded executor queue causing OutOfMemoryError, a mutable map key leaking memory, a parallelStream saturating the common pool. One concrete incident, with its symptom and fix, is worth more than ten definitions.

Remember this

  1. 1

    A strong answer has a shape. Start with a one-sentence definition, then explain the mechanism (what the compiler or JVM really does), then give a tiny example, then name the trap or trade-off. For "what is the String pool?" that is: a cache of String literals in the heap; the compiler puts literals in the class file's constant pool and the JVM shares one object per distinct literal; "a" == "a" is true but new String("a") == "a" is false; so always compare with equals.

  2. 2

    Interviewers ask in families. One question about HashMap leads to hashCode, then to collisions, then to treeification, then to ConcurrentHashMap. Learn each family as a story, not a list of facts: if you understand that a HashMap is an array of buckets indexed by a hash, every follow-up is a consequence you can reason out on the spot.

  3. 3

    The most asked areas, in rough order: **equals and hashCode (Topic 4.8), HashMap internals (Topic 9.4), String immutability and the pool (Topic 6.1), checked vs unchecked exceptions (Topic 7.3), overloading vs overriding (Topics 3.4 and 5.3), Java 8 features (Phase 10), synchronized vs volatile (Topics 13.3 and 13.4), thread pools (Topic 13.6) and garbage collection** (Topic 14.3).

  4. 4

    Many questions have a version in them. "Can an interface have method bodies?" is "no" before Java 8 and "yes, default and static methods" after it. "Where is the String pool?" is "PermGen" before Java 7 and "the heap" since. Saying which version a fact applies to is a quick way to sound senior, and the course's since tags (Topic 0.3) exist for exactly this.

  5. 5

    When you don't know, reason out loud from what you do know. "I don't remember the exact threshold, but I know long bucket chains make lookups linear, so Java must convert them to something faster past some length; I believe it's a red-black tree." That answer scores far better than silence, and it is how real engineers work.

  6. 6

    Back answers with code you can run. The examples on this page prove the facts people get wrong: two equal keys that a HashMap can't find, two equal Strings that aren't ==, a loop that throws ConcurrentModificationException, and a stream that does nothing until a terminal operation runs.

Explain it without notes

01

[JVM] What is the difference between the JDK, the JRE and the JVM?

02

[JVM] Is Java compiled or interpreted? Why is it called platform independent?

03

[JVM] What lives on the stack and what lives on the heap?

04

[JVM] How does class loading work, and what is parent delegation?

05

[String] Why is String immutable?

06

[String] What is the String pool, and when does == work on Strings?

07

[String] String vs StringBuilder vs StringBuffer: when do you use each?

08

[equals/hashCode] What is the equals and hashCode contract, and what breaks if you override only equals?

09

[equals/hashCode] Can you use a mutable object as a HashMap key?

10

[Collections] How does HashMap work internally?

11

[Collections] What changed in HashMap in Java 8, and why?

12

[Collections] ArrayList vs LinkedList: which is faster, and when?

13

[Collections] HashMap vs Hashtable vs ConcurrentHashMap?

14

[Collections] What are fail-fast and fail-safe iterators?

15

[Collections] Comparable vs Comparator?

16

[Collections] What is the difference between List.of, Arrays.asList and Collections.unmodifiableList?

17

[Exceptions] Checked vs unchecked exceptions, and Error vs Exception?

18

[Exceptions] Does finally always run? What if finally has a return?

19

[Exceptions] What does try-with-resources do, and what is a suppressed exception?

20

[Generics] What is type erasure, and what can't you do because of it?

21

[Generics] Explain wildcards and PECS.

22

[OOP] Overloading vs overriding? Can you override a static method?

23

[OOP] Abstract class vs interface, after Java 8?

24

[OOP] Is Java pass-by-value or pass-by-reference?

25

[OOP] final vs finally vs finalize?

26

[Java 8+] What were the main features of Java 8?

27

[Java 8+] Intermediate vs terminal stream operations, and map vs flatMap?

28

[Java 8+] How should Optional be used, and how should it not?

29

[Java 8+] What is a record, and what does the compiler generate?

30

[Java 8+] What are sealed classes, and how do they work with pattern matching?

31

[Concurrency] synchronized vs volatile?

32

[Concurrency] Runnable vs Callable, and why use an ExecutorService?

33

[Concurrency] What is a deadlock, and how do you prevent one?

34

[Concurrency] How does ConcurrentHashMap achieve thread safety?

35

[Concurrency] What are virtual threads, and when do they help?

36

[GC] How does garbage collection work, and which collector is the default?

37

[GC] Can a Java program have a memory leak?

38

[GC] OutOfMemoryError vs StackOverflowError?

Practice

01

Write a Money class with a long cents and a String currency that is safe to use as a HashMap key. Prove it with a map lookup using a separate but equal object.

02

Write a thread-safe hit counter that 4 threads increment 10,000 times each, and print the total. Use the simplest correct tool.

03

Given a list of words, use a stream to count how many words start with each letter, in alphabetical order of letter.

04

Show the difference between orElse and orElseGet with a method that prints when it is called.

Trade-offs

  • ↔

    Breadth vs depth: an interview rewards a deep, correct answer about a few areas more than shallow recall of everything. Go deep on HashMap, equals/hashCode, exceptions and concurrency first.

  • ↔

    Memorised numbers vs reasoning: thresholds such as 0.75 and 8 are good to know, but explaining *why* a threshold exists is worth more than the number itself.

  • ↔

    Mentioning versions shows depth, but only state a version you are sure of; a wrong version undermines an otherwise good answer.

Done when you can

  • Done when you can answer each question above aloud in under two minutes using definition, mechanism, example, trap.

  • Done when you can draw HashMap's put path from hashCode to treeification.

  • Done when you can write a correct equals and hashCode pair without help, and explain what breaks without it.

  • Done when you can name the headline features of Java 8, 11, 17 and 21.

  • Done when you can explain synchronized vs volatile and how ConcurrentHashMap avoids a global lock.

  • Done when you can describe how the GC decides an object is garbage and name the default collector.