Study guide
6.4 The Map Interface, Sorting, Comparable, and Comparator
Oracle Java SE 17 Developer Certified Professional 1Z0-829
Track your progress as you read
Finished sections get a check mark.
1 Introduction: The 1Z0-829 Exam
About the Java SE 17 Developer (1Z0-829) Exam
2 Chapter 1: Java Fundamentals & Language Basics
1.1 Primitive Types, Literals, Wrapper Classes, and Type Promotion/Casting 1.2 Local Variable Type Inference (`var`) Rules and Scoping 1.3 Operators, Precedence, Evaluation Order, and Short-Circuit Evaluation 1.4 Text Blocks, String Immutability, and StringBuilder APIs
3 Chapter 2: Program Flow & Decision Constructs
2.1 Conditional Branching with if/else and the Ternary Operator 2.2 Switch Statements and Switch Expressions 2.3 Iteration Constructs, Loop Control, and Branching Labels
4 Chapter 3: Object-Oriented Design & Class Mechanics
3.1 Class Declarations, Field/Method Signatures, and Access Modifiers 3.2 Constructors, Overloading, Initialization Order, and Garbage Collection 3.3 Inheritance, Method Overriding, Polymorphism, and `super`/`this` 3.4 Abstract Classes, Static Members, and Object Methods (`equals`, `hashCode`, `toString`)
5 Chapter 4: Advanced OOP: Interfaces, Records & Sealed Types
4.1 Interface Architecture: Default, Static, and Private Methods 4.2 Enumerations: Constants, Constructors, Methods, and Custom Bodies 4.3 Records: Canonical/Compact Constructors, Components, and Immutability 4.4 Sealed Classes and Interfaces: `permits`, Hierarchy Constraints, and Modifiers
6 Chapter 5: Pattern Matching & Nested Types
5.1 Pattern Matching for `instanceof` and Flow Scoping Mechanics 5.2 Nested Types: Member Inner, Static Nested, Local, and Anonymous Classes 5.3 Defensive Programming, Immutability Patterns, and Validation
7 Chapter 6: Generics, Collections & Arrays
6.1 Generic Classes, Interfaces, Methods, and Type Erasure 6.2 Bounded Type Parameters and Wildcards (PECS Rule) 6.3 Collections Framework: List, Set, Queue, and Deque APIs 6.4 The Map Interface, Sorting, Comparable, and Comparator 6.5 Arrays: Declaration, Initialization, Multidimensional Arrays, and the Arrays Utility Class
8 Chapter 7: Functional Programming & Lambda Expressions
7.1 Functional Interfaces and Lambda Syntax Rules 7.2 Standard Functional Interfaces in `java.util.function` 7.3 Method References: Static, Bound, Unbound, and Constructor References
9 Chapter 8: The Stream API
8.1 Stream Lifecycle: Creation, Pipeline Architecture, and Lazy Evaluation 8.2 Intermediate Stream Operations: Filtering, Mapping, Sorting, and Slicing 8.3 Terminal Stream Operations: Reduction, Matching, Finding, and Collecting 8.4 Primitive Streams (`IntStream`, `LongStream`, `DoubleStream`) and Numeric Statistics
10 Chapter 9: Advanced Streams & Collectors
9.1 The Optional Class: Safe Null Handling, Transformation, and Chaining 9.2 The Collectors API: Downstream Reductions, Grouping, and Partitioning 9.3 Parallel Streams: Fork/Join Pool, Spliterators, and Concurrency Pitfalls
11 Chapter 10: Exception Handling
10.1 The Java Exception Hierarchy: Checked vs. Unchecked Exceptions and Errors 10.2 Exception Constructs: `try-catch-finally`, Multi-Catch, and Rethrowing 10.3 Try-With-Resources, `AutoCloseable`, Suppressed Exceptions, and Custom Exceptions
12 Chapter 11: Date/Time API & Localization
11.1 Date and Time Core Types: `LocalDate`, `LocalTime`, `LocalDateTime` 11.2 Timestamps, Intervals, and Durations: `Instant`, `Period`, and `Duration` 11.3 Time Zones, Daylight Saving Time (DST) Offsets, and `ZonedDateTime` 11.4 Internationalization and Localization: `Locale`, `ResourceBundle`, and Formatters 11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates
13 Chapter 12: Java Platform Module System (JPMS)
12.1 Module Architecture, `module-info.java`, and Module Paths 12.2 Module Directives: `requires`, `requires transitive`, `exports`, and Qualified Exports 12.3 Reflection, Deep Encapsulation, `opens`, and Open Modules 12.4 Services in JPMS (`uses`, `provides...with`), Migration Paths, and Tooling (`jlink`, `jdeps`) 12.5 Compiling and Packaging Code: Non-Modular JARs, Modular JARs, and Migration Strategies
14 Chapter 13: Concurrency & Multithreading
13.1 Thread Fundamentals, `Runnable`, `Callable`, and Thread Lifecycle 13.2 Memory Visibility, `volatile`, Intrinsic Locks, and Synchronization 13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future` 13.4 Concurrent Collections, Atomic Variables, Explicit Locks, and `CompletableFuture`
15 Chapter 14: Java I/O and NIO.2
14.1 Classical I/O: Byte and Character Streams, Readers, Writers, and Buffering 14.2 Object Serialization, `Serializable`, `transient`, and `serialVersionUID` 14.3 NIO.2 Architecture: `Path`, `Paths`, and Basic `Files` Operations 14.4 Advanced NIO.2: Directory Walking, Streams (`Files.lines`, `walk`), and `WatchService`
16 Chapter 15: Accessing Databases with JDBC
15.1 JDBC Architecture, Drivers, `DriverManager`, and `DataSource` Connections 15.2 SQL Execution: `Statement`, `PreparedStatement`, and `CallableStatement` 15.3 `ResultSet` Navigation, Data Types, and Transaction Management (Commit, Rollback, Savepoints)
17 Chapter 16: Annotations & the Java Logging API
16.1 Standard Annotations: @Override, @FunctionalInterface, @Deprecated, @SuppressWarnings, and @SafeVarargs 16.2 Java Logging API Basics: Logger, Levels, Handlers, and Configuration
6.4 The Map Interface, Sorting, Comparable, and Comparator
Key Takeaways Explain This Topic AI
Map implementations manage key-value pairs outside the Collection hierarchy: HashMap provides O(1) hash bucket lookups, LinkedHashMap preserves insertion/access order, and TreeMap guarantees O(log n) key-sorted traversal.
Keys in hash-based collections must adhere strictly to the equals and hashCode contract; mutating key state after insertion alters the hash code and permanently strands entries in unreachable buckets.
Modern Map functional methods (computeIfAbsent, computeIfPresent, compute, merge) execute atomic updates; returning null from a remapping function removes the corresponding entry from the map.
Comparable<T> defines intrinsic natural ordering via int compareTo(T o), which must remain consistent with equals() to prevent TreeSet and TreeMap from discarding non-identical elements as duplicates.
Comparator<T> provides external custom ordering through int compare(T o1, T o2) and fluent combinators (comparing, thenComparing, reversed, nullsFirst, nullsLast).
Last updated: October 2026
6.4 The Map Interface, Sorting, Comparable , and Comparator
Mapping keys to values and establishing precise sort orders are foundational operations in enterprise Java development. The Map<K, V> interface provides key-value associations without extending Collection . On the 1Z0-829 exam, questions frequently test the inner workings of hash bucket resolution, the strict equals() and hashCode() contract, modern lambda-enabled Map methods ( merge , computeIfAbsent ), and complex multi-tiered sorting using Comparable and Comparator combinators.
The Map Interface and Implementations
A Map<K, V> maps unique keys to values, prohibiting duplicate keys. Its primary implementations offer distinct performance and ordering trade-offs:
1. HashMap
Internal Structure : An array of hash buckets. Collisions are stored in linked lists; when a bucket exceeds 8 entries and total table capacity reaches at least 64, the bucket transforms into a balanced red-black tree ( TreeNode ) to guarantee O ( log n ) O(\log n) O ( lo g n ) worst-case lookup rather than O ( n ) O(n) O ( n ) .
Null Policy : Allows one null key and multiple null values.
Ordering : No ordering guarantees; bucket order shifts when resizing.
2. LinkedHashMap
Internal Structure : Extends HashMap while maintaining a doubly-linked list through all entries.
Ordering Modes : Defaults to insertion order . Can be configured via its constructor ( new LinkedHashMap<>(16, 0.75f, true) ) to track access order , making it an ideal foundation for Least-Recently-Used (LRU) caches when combined with removeEldestEntry() .
3. TreeMap
Internal Structure : A Red-Black tree implementing NavigableMap<K, V> .
Ordering : Keys are sorted according to natural ordering ( Comparable ) or an explicit Comparator .
Null Policy : Prohibits null keys when using natural ordering (throws NullPointerException ). Allows null values.
Performance : O ( log n ) O(\log n) O ( lo g n ) for get , put , remove , and containsKey . NavigableMap<Integer, String> treeMap = new TreeMap<>();
- treeMap.put(10, "Ten");
- treeMap.put(20, "Twenty");
- treeMap.put(30, "Thirty");
- System.out.println(treeMap.lowerKey(20)); // 10 (greatest key < 20)
- System.out.println(treeMap.floorKey(20)); // 20 (greatest key <= 20)
- System.out.println(treeMap.ceilingKey(25)); // 30 (least key >= 25)
- System.out.println(treeMap.higherKey(20)); // 30 (least key > 20)
- The equals() and hashCode() Contract
Hash-based collections ( HashMap , HashSet ) use an object's hashCode() to determine its bucket index, and equals() to resolve bucket collisions. The contract mandates:
If a.equals(b) is true , then a.hashCode() == b.hashCode() must be true .
If a.hashCode() == b.hashCode() , a.equals(b) is not required to be true (hash collision).
If a.equals(b) is false , hash codes are not required to be distinct, though unique hash codes optimize performance.
The Mutable Key Hazard
If an object used as a map key is mutated such that its hashCode() changes, the entry becomes permanently lost: class AccountKey {
- int accountId;
- AccountKey(int id) { this.accountId = id; }
- public boolean equals(Object o) {
- return o instanceof AccountKey k && this.accountId == k.accountId;
- }
- public int hashCode() { return accountId; }
- }
- Map<AccountKey, String> map = new HashMap<>();
- AccountKey key = new AccountKey(101);
- map.put(key, "Active");
- // Mutate key field after insertion
- key.accountId = 999;
// Lookup computes hashCode 999, searching the wrong bucket!
System.out.println(map.get(key)); // Prints null! Entry is stranded.
Warning
Always use immutable types (such as String , Integer , or Java 16 record types) as map keys to guarantee hash code stability.
Modern Functional Map Methods (Java 8+)
Java 8 introduced powerful methods on Map that accept lambdas for atomic modifications:
1. getOrDefault(key, defaultValue)
Returns the value mapped to key , or defaultValue if the key is not found or is explicitly mapped to null .
2. putIfAbsent(key, value)
Inserts value only if key is absent or currently mapped to null . Returns the existing value, or null if the new value was placed.
3. computeIfAbsent(key, k -> compute(k))
If key is absent or mapped to null , evaluates the mapping function. If the function returns non-null, inserts the result and returns it. If the function returns null , no entry is created.
4. computeIfPresent(key, (k, v) -> compute(k, v))
If key is present and mapped to a non-null value, executes the remapping function with (key, oldValue) .
If the function returns non-null, updates the entry.
CRITICAL TRAP : If the function returns null , the entry is removed from the map !
5. compute(key, (k, v) -> compute(k, v))
Executes the remapping function regardless of whether the key exists ( v will be null if absent).
If the function returns non-null, inserts or updates the entry.
If the function returns null , removes the entry (or leaves it absent).
6. merge(key, value, (oldVal, newVal) -> remap)
The merge method has the most surprising rules of the group. It takes a key, a non-null value , and a BiFunction remapping function:
If key is absent or mapped to null : associates key directly with value . The remapping function is never invoked !
If key is present with non-null oldVal : invokes remappingFunction.apply(oldVal, value) .
If the function returns non-null, updates the key with the returned result.
CRITICAL TRAP : If the function returns null , the key is removed from the map !
If the value argument passed to merge is null , it throws NullPointerException immediately. Map<String, Integer> scores = new HashMap<>();
- scores.put("Alice", 90);
- scores.put("Bob", 50);
- // 1. Existing key: invokes lambda (90 + 10 = 100)
- scores.merge("Alice", 10, (oldVal, newVal) -> oldVal + newVal); // Alice=100
- // 2. Absent key: assigns 75 directly without calling lambda
- scores.merge("Carol", 75, (oldVal, newVal) -> oldVal + newVal); // Carol=75
// 3. Lambda returns null: REMOVES key from map!
scores.merge("Bob", 50, (oldVal, newVal) -> null); // Bob is removed!
- System.out.println(scores); // Prints {Alice=100, Carol=75}
- Sorting with Comparable<T> vs. Comparator<T>
Java provides two interfaces to define order:
- Dimension Comparable<T> Comparator<T>
- Package java.lang java.util
- Definition Site Defined within the domain class itself Defined externally as separate classes or lambdas
- Abstract Method int compareTo(T other) int compare(T o1, T o2)
- Role Natural intrinsic ordering Custom, multiple, or dynamic sort orders
- Sorting Invocations Collections.sort(list) list.sort(comparator) / Collections.sort(list, comparator)
- The compareTo Contract and TreeSet / TreeMap
The compareTo(T o) method returns:
- A negative integer if this < o
- Zero if the two objects are equal in sort order (ideally only when this.equals(o) is also true )
- A positive integer if this > o
Warning
The TreeSet / TreeMap Consistency with Equals Trap TreeSet and TreeMap determine element equality and uniqueness using compareTo() (or compare() ), not equals() ! If a.compareTo(b) == 0 , a TreeSet treats b as an exact duplicate of a and discards it—even if a.equals(b) is false ! Always ensure natural ordering is consistent with equals() .