Every 2–5-year Core Java and Java 8+ question — collections internals, immutability, generics, memory, streams, functional interfaces, Optional — as a one-line answer linked to the full answer.
Published September 25, 2026
This page condenses every question from the 2 to 5 Years course in these areas into a single line: the question, linked to its full answer, and the one-sentence answer you should be able to give instantly. Read down the list and answer each question aloud before reading the line. Wherever you hesitate, follow the link and revise the full answer — interviewers at your level expect these basics to be fluent, and they often open with them before going deeper.
Intermediate OOP & Language Features — Interview Questions — open the lesson
build().final on inheritance? — A final method can't be overridden, so every subclass inherits exactly that implementation. Use it to protect behaviour that invariants or security depend on.instanceof, or with the type system.Auditable entities may be passed to an audit writer, or only Transmittable objects may be sent outside the network boundary.java.util.Date and java.sql.Date). In a file that uses both, import one, and refer to the other by its fully qualified name.public, if it really is part of the API; Expose its behaviour through a public interface or facade in the same package (the usual design); For tests, put the test in the…final variable? — Yes. final fixes the reference, not the object. You can't reassign the variable, but you can call mutating methods on the object it points to.protected (which adds subclasses in other packages), and less restrictive than private.Enums, Generics, Pass-by-Value & Imports — Interview Questions — open the lesson
final class extending java.lang.Enum, with one public static final instance per constant.java.lang.Enum, and Java classes have only one superclass. Enums can implement interfaces, which is how you share behaviour, or make them pluggable.java.lang.Enum is already its superclass. When interviewers repeat the question, they're usually checking the follow-up: "so how would you share code between enums?" Use a common interface with default methods, or delegate to a helper…values() method. It returns a new array of the constants, in declaration order.values() with a for-each loop, EnumSet.allOf(...), or a stream over values(). To look a constant up by name, use Enum.valueOf(Type.class, "NAME") or Type.valueOf("NAME").<> (Java 7) lets the compiler infer the generic type arguments of a constructor call from the context, so you don't repeat them: Map<String, List<Order>> byCustomer = new HashMap<>();.ArrayStoreException).import and import static? — import brings types into scope by simple name. import static brings a class's static members (methods and constants) into scope, so you can call max(a, b) instead of Math.max(a, b).Collectors.*, TimeUnit), they make code read naturally.Cart object holds CartItems; CheckoutService (a Spring singleton) turns the cart into an Order, asks a PaymentGateway (interface → RazorpayGateway object) to charge it, saves the order through an OrderRepository, and publishes an…this be used in a static method or a static block? — No. this refers to the current instance, and static methods and static initialisers run without one. They belong to the class, and run even when no object exists.Collections Internals & Scenarios — Interview Questions — open the lesson
PriorityQueue, and why it beat other queues. — Whenever items must be processed by priority, not arrival order. For example: a job scheduler running the earliest-deadline job first; a notification dispatcher where OTPs jump ahead of marketing emails; keeping the top-K items from a stream.HashMap keys? — The entry is stored in a bucket chosen by the key's hash at insertion time. If you then mutate a field that hashCode() uses, lookups compute a different hash, search the wrong bucket, and can't find the entry.equals() but not hashCode()? — It breaks the contract that equal objects must have equal hash codes. Two logically equal keys get different identity hashes, land in different buckets, and never get compared with equals.HashMap and IdentityHashMap differ in handling keys? — HashMap compares keys with equals()/hashCode(), which is logical equality. IdentityHashMap compares with == and System.identityHashCode, which is reference equality.Collections.sort() work internally? — Collections.sort(list) calls list.sort(null). The default List.sort copies the list into an array, sorts it with Arrays.sort(Object[]) → TimSort, and writes the elements back.null with Collections.sort()? — With natural ordering, compareTo is called on or with null, which throws a NullPointerException. (A one-element list is returned unchanged without comparing, so List.of(null)-like single-element cases don't throw.) Handle nulls explicitly with a null-safe comparator —…Collections.sort() without a comparator? — Only if the class implements Comparable<T>, which defines its natural ordering in compareTo. Otherwise, sorting fails at runtime with a ClassCastException ("cannot be cast to class java.lang.Comparable").Collections.sort() and Stream.sorted()? — Compared side by side in the full answer (table) — know each row.ArrayList's initial capacity when the list is cleared and reused over and over? — Size it for the typical peak batch (new ArrayList<>(expectedMax)), to avoid repeated growth copies on the first fill.equals() and hashCode() over the fields that define the object's identity or value, following the contract (reflexive, symmetric, transitive, consistent, and false for null).HashMap. How do you make it thread-safe? — Replace it with a ConcurrentHashMap, which allows many concurrent readers and writers with fine-grained locking, and use its atomic compound methods.TreeSet order custom objects (not wrapper classes)? — A TreeSet is backed by a red-black tree (a TreeMap). It orders elements using either: their natural ordering, which requires implementing Comparable; or; a Comparator passed to the constructor.TreeSet sort objects? (Follow-up: what about duplicates?) — Same mechanism as Q12, with the key follow-up: TreeSet decides uniqueness by comparison, not equals. If your comparator says two different employees compare as 0, for example because they have the same salary, the second one is silently dropped.JVM, Memory & Class Loading — Interview Questions — open the lesson
String object holds a byte[] plus a coder flag. Since Java 9 (compact strings), text that fits in Latin-1 uses one byte per character, and anything else uses UTF-16 (two bytes per character).Class object. Loading is lazy: a class loads when it's first actively used. There are three built-in loaders, arranged in a parent-delegation hierarchy: Bootstrap: core java.base classes. It's native, and appears…Class objects.-Xlog:class+unload; Watch Metaspace usage in JFR, or jcmd <pid> VM.metaspace; Take a heap dump, and look for multiple instances of your web app's class loader (Eclipse MAT's…Class object and static fields live on the heap.OutOfMemoryError: Metaspace, or a pod killed for exceeding its memory limit while the heap looks fine. The causes: too many generated classes (for example, unbounded dynamic proxies or scripting engines), or class-loader leaks on redeploy.…jcmd <pid> GC.heap_dump file.hprof, or automatically with -XX:+HeapDumpOnOutOfMemoryError; Analyse it in Eclipse MAT: the Leak Suspects report,…static keyword affect memory management? — Static fields are allocated once per class (per class loader), when the class is initialised. Since Java 8 they're stored on the heap, together with the class's java.lang.Class object.Exception Design & Serialization Edge Cases — Interview Questions — open the lesson
class Config implements Serializable { static String region = "ap-south-1";writeObject aborts, and the exception propagates to the caller: NotSerializableException for a non-serializable object in the graph; InvalidClassException for class problems; a plain IOException for stream or disk failures; anything your custom writeObject throws.Serializable class has a member that isn't serializable. What happens, and how do you fix it? — Serialization throws java.io.NotSerializableException, naming the offending class. The fixes are: Make the member's class Serializable, if you own it; Mark the field transient (and rebuild it after deserialization, lazily or in readObject); Use custom…NoClassDefFoundError and ClassNotFoundException? — Compared side by side in the full answer (table) — know each row.ExceptionInInitializerError, wrapping the cause. The class is then marked as erroneous.finally block? Describe a scenario. — Typical real uses are guaranteed cleanup that isn't an AutoCloseable: releasing a ReentrantLock (lock.unlock() in finally); restoring the thread's state in a pool (MDC.clear(), threadLocal.remove()); resetting a flag or metrics timer; releasing a semaphore permit.finally block ever caused unexpected behaviour? — The common surprises: An exception thrown in finally masks the original exception from try. For example, close() fails and hides the real error. try-with-resources fixes this by attaching close failures as suppressed exceptions; return in finally swallows exceptions…Throwable bad practice? — Throwable includes Errors: OutOfMemoryError, StackOverflowError and LinkageError. After one of those, the JVM or application may be in an inconsistent state.Lambdas, Functional Interfaces & Method References — Interview Questions — open the lesson
java.util.function); the Stream API; default and static interface methods; …(params) -> body, that implements the single abstract method of a functional interface.this) inside its body, for example to unregister itself as a listener.default and static methods is fine, and so are abstract methods that just redeclare public Object methods (like equals).java.util.function. The core four and their families.this and super inside a lambda? — Yes. Because a lambda doesn't introduce a new scope or object identity, this and super refer to the enclosing class instance and its superclass, exactly as they would in the surrounding method.Function and Consumer don't. The options: Catch the exception inside the lambda, and handle it or wrap it; Wrap it in an…synchronized inside a lambda? — Yes, a synchronized block inside the lambda body is perfectly legal: () -> { synchronized (lock) { … } }. What you can't do is mark the lambda itself synchronized, because lambdas have no method modifiers.Default Methods, Backward Compatibility & Optional — Interview Questions — open the lesson
InterfaceName.super.method(), or combine them.default keyword), which implementing classes inherit and may override.AbstractMethodError).Optional, and how is it used? — Optional<T> is a container that is either empty, or holds a non-null value. It makes "there may be no result" explicit in a method's return type, and it offers functional methods for handling both cases, instead of scattered null checks.Optional? — Wrap the possibly-null value with Optional.ofNullable(value), then transform it and supply defaults without explicit checks — String displayName = Optional.ofNullable(user.nickname())Optional.of() and Optional.ofNullable()? — Optional.of(value) requires a non-null value. It throws NullPointerException immediately if the value is null, which is useful as an assertion.Optional as a method parameter? — Generally no: It makes call sites awkward (search(Optional.empty())); It doesn't stop callers passing null for the Optional itself; It adds an allocation; Overloads, or a nullable parameter documented as such, are clearer.Stream API Internals (Part 1) — Interview Questions — open the lesson
filter, map, sorted), and one terminal operation (collect, reduce, forEach).map and flatMap? — map is one-to-one: each element becomes exactly one new element. flatMap is one-to-many: each element becomes a stream of elements, and those streams are flattened into one.map() vs flatMap(): when is each the right tool? (Rephrased, with Optional) — Use map when the function returns a plain value, and flatMap when it already returns a container (Stream, Optional), so you avoid nesting (Stream<Stream<T>>, Optional<Optional<T>>).peek() and map(), and when should peek be used carefully? — map transforms elements, and its result replaces them in the stream. peek runs a side-effecting action and passes the same element along unchanged.stream(), then filter(predicate), then collect. filter keeps the elements for which the predicate returns true.findFirst() and findAny()? — Both are short-circuiting terminal operations returning an Optional. findFirst respects encounter order, and always returns the first matching element.Collectors class? — Collectors supplies ready-made mutable-reduction recipes for collect(): To collections: toList, toSet, toMap, toCollection, and the toUnmodifiable… variants; Joining strings: joining; Grouping and partitioning: groupingBy, partitioningBy; Aggregation:…forEach() method? — Java 8 added forEach in two places: Iterable.forEach(Consumer), a default method: internal iteration over any collection; Stream.forEach, a terminal operation.parallelStream(), or .parallel(), splits the source using its Spliterator, and processes the chunks as tasks in the common ForkJoinPool (with a size equal to the number of cores minus 1, plus the calling thread), then combines the partial results.Predicate interface? — Predicate<T> represents a boolean-valued condition, boolean test(T t). It's used by filter, removeIf, anyMatch/allMatch/noneMatch, and takeWhile/dropWhile.Stream API Internals (Part 2) — Interview Questions — open the lesson
Stream.iterate(seed, next) (each element is derived from the previous one), or Stream.generate(supplier) (independent values).Function interface, and how is it used? — Function<T, R> represents a transformation, R apply(T t). It's what map takes. It composes: f.andThen(g) means apply f, then g, and f.compose(g) means apply g, then f.stream().sorted() for natural order, or sorted(comparator), then collect. The source isn't modified.Comparator factory methods, and pass it to sorted, max, min or collectors such as maxBy, or to a TreeMap supplier in toMap/groupingBy.sorted() work internally, with natural ordering versus a comparator? — In both cases, sorted() is a stateful barrier. It buffers every upstream element (into an array or list), sorts the buffer once the upstream is exhausted, and only then pushes elements downstream.reduce() used for? — reduce folds all the elements into a single value with an associative function. It has three forms: reduce(identity, accumulator): returns T; reduce(accumulator): returns Optional<T> (the stream may be empty); reduce(identity, accumulator, combiner): for reducing…filter() work? — filter(Predicate) is a lazy, stateless intermediate operation. As each element reaches it during the terminal operation's single pass, the predicate is evaluated.Collectors.toList()? How does it compare with Stream.toList()? — collect(Collectors.toList()) gathers the elements into a new List. In practice that's an ArrayList, but no guarantee is made about its type, mutability or thread-safety.Stream.of() work? — Stream.of(T... values) creates a sequential, ordered stream from its arguments. Stream.of(single) creates a one-element stream.limit() and skip()? — limit(n) keeps at most the first n elements, and short-circuits: upstream stops producing after n. skip(n) discards the first n elements, and passes the rest.collect(Collectors.toMap(keyMapper, valueMapper)). Know its three traps: Duplicate keys throw an IllegalStateException. Pass a merge function; null values throw an NPE (a HashMap.merge limitation); There's no ordering. Pass a map supplier (LinkedHashMap::new,…Stream.iterate() and Stream.generate()? — iterate(seed, f) produces a sequence where each element depends on the previous one (seed, f(seed), f(f(seed))…), and it's ordered.count(), sum() and reduce()? — count() returns the number of elements, as a long. It's on every stream, and can skip executing the pipeline when the size is known; sum() adds up the elements. It's only on primitive streams (IntStream, LongStream, DoubleStream), with no boxing, and it returns 0…Stream Coding Problems (Level 2, Part 1) — Interview Questions — open the lesson
List<Integer> evens = nums.stream().filter(n -> n % 2 == 0).toList();List<Integer> startsWith1 = nums.stream() .filter(n -> String.valueOf(n).startsWith("1"))List<Integer> duplicates = nums.stream() .collect(Collectors.groupingBy(Function.identity(),…Optional<Integer> first = nums.stream().findFirst();long total = nums.stream().count();int max = nums.stream().max(Comparator.naturalOrder()).orElseThrow();String input = "Java articles are Awesome"; Optional<Character> firstUnique = input.chars()List<Integer> ascending = nums.stream().sorted().toList();List<Integer> descending = nums.stream().sorted(Comparator.reverseOrder()).toList(); List<Integer>…true if any value appears at least twice. — static boolean containsDuplicate(int[] nums) { return Arrays.stream(nums).distinct().count() != nums.length;Stream Coding Problems (Level 2, Part 2) — Interview Questions — open the lesson
LocalDate today = LocalDate.now();Stream<String> all = Stream.concat(list1.stream(), list2.stream()); List<String> merged = Stream.of(list1,…List<Integer> cubes = List.of(4, 5, 6, 7, 1, 2, 3).stream() .map(i -> i * i * i)int[] arr = { 99, 55, 203, 99, 4, 91 }; Arrays.sort(arr);map to convert strings to uppercase. — List<String> upper = names.stream().map(s -> s.toUpperCase(Locale.ROOT)).toList();toMap with a merge function and a map supplier. Here, notes are keyed by tag name, and the map is ordered by tag ID, descending — record Note(int id, String tagName, long tagId) { } List<Note> notes = List.of(new Note(1, "note1", 11),…List<String> names = List.of("AA", "BB", "AA", "CC"); Map<String, Long> counts = names.stream()Map<String, Long> duplicates = names.stream() .collect(Collectors.groupingBy(Function.identity(),…Optional and print each element. — Optional.ofNullable(notes) .orElseGet(List::of)static int findMax(int[] arr) { return Arrays.stream(arr).max()String s = "string data to count each character"; Map<Character, Long> counts =…Q: How should I use this list in the last week before an interview? A: Do one pass per day. Cover the answer text, say your answer out loud, then check it. Mark every question you could not answer crisply, and spend your study time only on the marked ones by opening the linked full answer. By the third pass the marked list should be short.
Q: The interviewer asks one of these basics — should I give only the one-liner? A: Lead with the one-liner, then add one concrete detail or example from your own work. At this level the follow-up usually probes the mechanism behind the basic answer, so be ready to go one layer deeper using the key points in the full lesson.
Q: Some answers here were corrected compared with common prep sheets — why? A: Several widely shared answers are outdated or wrong (for example, Java version details, removed Spring APIs, or SQL queries that miss edge cases). The full lessons call these out under "Common trap" — reading those is the fastest way to stand out from candidates who memorised the same sheets.