Free Java 21 OCP Practice Test 1

10 exam-style questions for 1Z0-830 β€” featuring Virtual Threads, Record Patterns & Sequenced Collections

10
Questions
20 min
Suggested Time
~65%
To Pass
Free
No Signup

πŸ“‹ About This Test

Test 1 focuses on what's new in Java 21: Virtual Threads, Pattern Matching for switch, Record Patterns, Sequenced Collections, and Stream API improvements.

πŸ†• Questions marked green cover features that are NEW in Java 21 and won't appear on the Java 17 OCP exam (1Z0-829).

Select an answer for each question, then click Submit & Show Answers to see your score with detailed explanations.

πŸ†• Question 1 β€” Virtual Threads

What is the output of this code using virtual threads?

import java.util.concurrent.*; try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { Future<String> future = executor.submit(() -> { Thread.sleep(100); return "done on " + Thread.currentThread(); }); String result = future.get(); System.out.println(result.contains("VirtualThread")); }

βœ… Correct Answer: A

Executors.newVirtualThreadPerTaskExecutor() creates an executor where each submitted task runs on its own virtual thread. When the task runs, Thread.currentThread() returns a VirtualThread instance whose toString() includes "VirtualThread", so contains("VirtualThread") is true.

Virtual threads fully support Thread.sleep() β€” that's actually one of their key benefits (they don't block carrier threads during sleep).

πŸ†• Question 2 β€” Sequenced Collections

What is the output?

import java.util.*; List<Integer> list = new ArrayList<>(List.of(2, 3, 4)); list.addFirst(1); list.addLast(5); System.out.println(list.getFirst() + " " + list.getLast() + " " + list.size());

βœ… Correct Answer: B

Java 21's JEP 431 introduces the SequencedCollection interface, which List now extends. This adds addFirst(), addLast(), getFirst(), getLast(), and reversed() methods directly on the List interface.

After operations: list = [1, 2, 3, 4, 5]. getFirst() = 1, getLast() = 5, size() = 5.

πŸ†• Question 3 β€” Record Patterns

What is the output?

record Point(int x, int y) {} Object obj = new Point(3, 4); if (obj instanceof Point(int a, int b)) { System.out.println(a + b); } else { System.out.println("not a point"); }

βœ… Correct Answer: C

Record patterns (Java 21) allow deconstruction of records directly in instanceof and switch. The pattern Point(int a, int b) matches the Point record and binds a to obj.x() (=3) and b to obj.y() (=4). Then a + b = 7.

This is one of the major new Java 21 OCP topics.

πŸ†• Question 4 β€” Pattern Matching for switch

What is the output?

Object obj = 42; String result = switch (obj) { case Integer i when i > 100 -> "big: " + i; case Integer i when i > 10 -> "medium: " + i; case Integer i -> "small: " + i; case String s -> "string: " + s; default -> "unknown"; }; System.out.println(result);

βœ… Correct Answer: B

Java 21 finalized pattern matching for switch with type patterns and guarded patterns (the when clause). The cases are evaluated in order:

(1) i > 100: 42 > 100 is false β€” skip
(2) i > 10: 42 > 10 is true β€” match! Returns "medium: 42"

The order of guarded patterns matters β€” the first matching case wins.

πŸ†• Question 5 β€” Stream.toList()

What is the difference between these two stream collectors?

import java.util.*; import java.util.stream.*; List<Integer> list1 = Stream.of(1, 2, 3).collect(Collectors.toList()); List<Integer> list2 = Stream.of(1, 2, 3).toList();

βœ… Correct Answer: C

Stream.toList() (added in Java 16, important for Java 21 OCP) returns an unmodifiable list β€” calling add(), remove(), etc. throws UnsupportedOperationException.

Collectors.toList() returns a modifiable ArrayList (typically).

This is a key exam distinction β€” prefer Stream.toList() when you want an immutable result, use Collectors.toList() when you need to modify the list.

Question 6 β€” Lambdas

Why does this code fail to compile?

import java.util.function.*; int counter = 0; Runnable r = () -> { counter++; System.out.println(counter); }; r.run();

βœ… Correct Answer: B

Lambdas (and inner classes) can only capture local variables that are effectively final β€” meaning they're never reassigned after initialization.

Here, counter++ is equivalent to counter = counter + 1, which reassigns counter. This violates the "effectively final" rule, so the code fails to compile.

To fix: use an AtomicInteger or an array of size 1.

πŸ†• Question 7 β€” Exhaustive Switch

What is true about this switch expression?

sealed interface Shape permits Circle, Square, Triangle {} record Circle(double r) implements Shape {} record Square(double s) implements Shape {} record Triangle(double b, double h) implements Shape {} static double area(Shape shape) { return switch (shape) { case Circle c -> Math.PI * c.r() * c.r(); case Square sq -> sq.s() * sq.s(); case Triangle t -> 0.5 * t.b() * t.h(); }; }

βœ… Correct Answer: A

Because Shape is a sealed interface, the compiler knows the complete set of permitted implementations (Circle, Square, Triangle). The switch covers all three, so it's exhaustive β€” no default case is needed.

This is one of the main benefits of sealed types + pattern matching.

Note: At runtime, passing null would throw NullPointerException, but the compiler doesn't require null handling unless you explicitly want to handle it with case null ->.

Question 8 β€” Files I/O

Which statement about this code is correct?

import java.nio.file.*; import java.util.*; Path path = Paths.get("data.txt"); List<String> lines = Files.readAllLines(path); lines.forEach(System.out::println);

βœ… Correct Answer: C

Files.readAllLines(path) reads the entire file into a List<String> in memory β€” fine for small files, but not for large ones. It throws checked IOException if the file doesn't exist or can't be read (assume try-catch in real code).

For large files, prefer Files.lines(path) which returns a Stream that must be closed in try-with-resources β€” that's the memory-efficient way.

Question 9 β€” Collectors

What is the result of this code?

import java.util.*; import java.util.stream.*; List<Integer> nums = List.of(1, 2, 3, 4, 5, 6); Map<Boolean, List<Integer>> result = nums.stream() .collect(Collectors.partitioningBy(n -> n % 2 == 0)); System.out.println(result.get(true).size() + " " + result.get(false).size());

βœ… Correct Answer: A

Collectors.partitioningBy(predicate) divides elements into two groups based on a boolean predicate. Always produces a Map with exactly two keys: true and false.

Even numbers (2, 4, 6) β†’ key true, 3 elements.
Odd numbers (1, 3, 5) β†’ key false, 3 elements.

Result: "3 3". Note that partitioningBy ALWAYS has both keys, even if one group is empty.

πŸ†• Question 10 β€” Stream.mapMulti()

What is the output?

import java.util.*; import java.util.stream.*; List<Integer> result = Stream.of(1, 2, 3) .<Integer>mapMulti((num, consumer) -> { consumer.accept(num); consumer.accept(num * 10); }) .toList(); System.out.println(result);

βœ… Correct Answer: B

Stream.mapMulti (Java 16+, key for Java 21 OCP) is an alternative to flatMap when you want to emit multiple elements per input. Instead of creating a Stream per element (like flatMap), you push elements directly to a Consumer.

For each input (1, 2, 3), the lambda pushes the number AND numberΓ—10. Output order is preserved: [1, 10, 2, 20, 3, 30].

mapMulti is often more efficient than flatMap when emitting few elements per input.

Answered 0 of 10 questions

πŸŽ‰ Test Complete!

0/10

Great work! Review your answers below.

Master Java 21 OCP with 2,074 Questions

You've experienced 10 questions. The full JavaOCP platform has 2,074 Java 21 OCP questions covering every exam topic β€” Virtual Threads, Record Patterns, Sequenced Collections, Pattern Matching, JPMS, and more.

That's 41 full certification tests for 1Z0-830, all with detailed explanations like the ones above.

Start 3-Day Free Trial β†’ Java 17 vs Java 21 Guide

From β‚Ή1,400 / $16 β€’ 6 months unlimited access