Skip to content

metodiev/EffectiveJava

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 

Repository files navigation

Effective Java – JDK 21 Edition

Language and Syntax Enhancements

Item 1: Master Pattern Matching for Switch (JEP 441)

Learn to use pattern matching in switch to simplify type checks and reduce boilerplate. Why it matters: Cleaner and safer polymorphic logic without casting. Challenge: Refactor a switch with instanceof checks into a pattern-matching switch. JEP 441 JEP 441: Pattern Matching for switch

Item 2: Explore Record Patterns (JEP 440)

Combine record patterns with pattern-matching to destructure immutable data directly. Why it matters: Enables concise, declarative data extraction. Challenge: Write a record Point(int x,int y) and destructure it in a switch. JEP 440 JEP 440: Record Patterns

Item 3: Use Sequenced Collections (JEP 431)

Understand new interfaces SequencedCollection, SequencedSet, SequencedMap. Why it matters: Unified first/last element access and reverse iteration. Challenge: Implement an LRU cache using SequencedMap. JEP 431 JEP 431 Sequenced Collections

Item 4: Learn String Templates (Preview – JEP 430)

Work with embedded expressions inside string literals. Why it matters: Eliminates messy concatenation and improves readability. Challenge: Write a log message builder using template expressions. JEP 430 JEP 430 String Templates

Item 5: Enhance Code with Records

Adopt records for immutable DTOs in APIs. Why it matters: Reduces boilerplate, supports equality and serialization easily. Challenge: Replace POJOs with records in a REST DTO layer.

Item 6: Explore Scoped Values (Preview – JEP 429)

Use scoped values for thread-local-like behavior without inheritance issues. Why it matters: Safer contextual data sharing in virtual threads. Challenge: Pass a security context using scoped values in a request handler. JEP 429 JEP Explore Scoped Values

Item 7: Prefer Sealed Classes for Controlled Inheritance (JEP 409)

Limit subclassing explicitly to improve domain modeling. Why it matters: Makes hierarchies explicit and maintainable. Challenge: Redesign a payment hierarchy with sealed interfaces. JEP 409

Item 8: Master Enhanced Switch Expressions (JEP 361)

Simplify control flow with expression switches returning values. Why it matters: Removes boilerplate break statements. Challenge: Replace if-else chains with switch expressions. JEP 361

Item 9: Use Text Blocks Effectively (JEP 378)

Adopt triple-quoted text for SQL, JSON, and HTML strings. Why it matters: Improves readability and reduces escape noise. Challenge: Store SQL queries as text blocks in a DAO. JEP 378

Item 10: Understand Null-Handling Patterns

Use pattern matching with null labels safely in switches. Why it matters: Prevents NPEs and documents null cases explicitly. Challenge: Handle null branches in pattern switches gracefully.

Concurrency and Threads

Item 11: Adopt Virtual Threads (JEP 444)

Experiment with lightweight threads to simplify concurrency. Why it matters: Enables millions of concurrent tasks with minimal overhead. Challenge: Rewrite a blocking I/O server using virtual threads. JEP 444

Item 12: Compare Platform vs Virtual Threads

Measure scheduling and memory overhead differences. Why it matters: Quantifies benefits before migration. Challenge: Benchmark 10 000 concurrent tasks under both models.

Item 13: Use Structured Concurrency (Incubator – JEP 453)

Manage child tasks as a unit for predictable cancellation. Why it matters: Simplifies error handling and resource cleanup. Challenge: Run concurrent HTTP calls with structured concurrency. JEP 453

Item 14: Use Executors.newVirtualThreadPerTaskExecutor()

Adopt new factory methods for simplicity. Why it matters: Reduces thread-pool configuration overhead. Challenge: Replace fixed pool executor with virtual thread executor.

Item 15: Avoid Thread-Locals in Virtual Threads

They’re costly and unnecessary with scoped values. Why it matters: Ensures scalability and correctness. Challenge: Refactor ThreadLocal usage to scoped values.

Item 16: Practice Reactive and Loom Integration

Blend reactive streams with virtual threads where useful. Why it matters: Learn migration paths from reactive to structured concurrency. Challenge: Convert one reactive flow into Loom-based structured concurrency.

Item 17: Tune ForkJoinPool for Virtual Threads

Understand scheduler implications. Why it matters: Ensures optimal CPU utilization. Challenge: Experiment with custom schedulers and measure throughput.

Item 18: Handle Cancellation and Timeouts

Learn to propagate cancellation via structured concurrency. Why it matters: Prevents leaked subtasks. Challenge: Implement a timeout-aware multi-API aggregator.

Item 19: Explore Thread.ofVirtual().factory()

Low-level creation for custom strategies. Why it matters: Gives fine-grained control of virtual thread creation. Challenge: Write a custom virtual thread naming factory.

Item 20: Integrate Virtual Threads with Spring Boot

Apply Loom inside web frameworks. Why it matters: Modernizes enterprise workloads easily. Challenge: Enable Loom executor in Spring Boot 3.2 app.

Collections and Streams

Item 21: Use List.getFirst()/getLast()

Simplify edge-element access. Why it matters: Cleaner alternative to index math. Challenge: Refactor algorithms using list.get(0) and list.get(list.size()-1).

Item 22: Apply reverseOrder() and reversed() in Sequenced Collections

Why it matters: Built-in reverse views simplify code. Challenge: Print lists backward using reversed() without copying.

Item 23: Use Map.firstEntry()/lastEntry()

Why it matters: Efficient boundary lookups. Challenge: Build a bounded cache that removes lastEntry() when full.

Item 24: Prefer unmodifiable Sequenced Collections

Immutable patterns prevent concurrent bugs. Challenge: Create read-only historical logs using unmodifiable sequenced lists.

Item 25: Explore Stream.toList() Behavior (JEP 430 context)

Why it matters: Returns unmodifiable list; understand when copying is needed. Challenge: Test mutation attempts on Stream.toList() output.

Item 26: Combine Stream.mapMulti()

Why it matters: Offers fine control for flattening. Challenge: Replace flatMap() with mapMulti() for conditional expansion.

Item 27: Use Optional.or() and ifPresentOrElse()

Why it matters: Avoids null checks elegantly. Challenge: Chain fallbacks using Optional.or().

Item 28: Use Collectors.teeing() for Combined Aggregations

Why it matters: Performs dual reductions. Challenge: Compute min and max in one pass.

Item 29: Explore Set.of() and Map.ofEntries() Immutables

Why it matters: Encourages functional design. Challenge: Replace mutable constants with immutable factory methods.

Item 30: Experiment with SequencedMap Views

Why it matters: Enables efficient LIFO/FIFO behaviors. Challenge: Implement deque-backed caching system.

Memory, Performance and JVM

Item 31: Explore G1 and ZGC Improvements

Why it matters: JDK 21 refines latency and footprint. Challenge: Profile GC pause times under G1 vs ZGC.

Item 32: Understand Generational ZGC (JEP 439)

Adds generational support to ZGC for better throughput. Challenge: Enable -XX:+UseZGC and compare heap metrics. JEP 439

Item 33: Learn about String Deduplication

Why it matters: Reduces memory duplication of identical strings. Challenge: Enable -XX:+UseStringDeduplication and inspect memory savings.

Item 34: Use Flight Recorder & JDK Mission Control

Why it matters: Built-in low-overhead profiling. Challenge: Record a 60-second app session and analyze hotspots.

Item 35: Explore Vector API (Incubator – JEP 448)

Why it matters: Unlocks SIMD performance. Challenge: Implement vectorized array math benchmark. JEP 448

Item 36: Use Foreign Function & Memory API (JEP 442)

Why it matters: Replaces JNI with safer, faster interop. Challenge: Call a native C function via MemorySegment. JEP 442

Item 37: Tune GC with Unified Logging

Why it matters: Simplifies diagnosis with -Xlog:gc*. Challenge: Collect GC logs and visualize with GCViewer.

Item 38: Analyze Class Data Sharing (CDS)

Why it matters: Faster startup for heavy apps. Challenge: Enable CDS and measure JVM cold-start times.

Item 39: Use AppCDS for Custom Workloads

Why it matters: Shares pre-loaded classes across JVMs. Challenge: Generate and apply a custom CDS archive.

Item 40: Study JVM’s Compact Strings Optimization

Why it matters: Understand how Latin-1 vs UTF-16 affects memory. Challenge: Measure heap for ASCII vs emoji-rich datasets.

Tooling and Development Experience

Item 41: Explore JDK 21 JShell Enhancements

Why it matters: Improves REPL exploration. Challenge: Prototype pattern-matching snippets in JShell.

Item 42: Automate with jlink and jpackage

Why it matters: Build minimal runtime images. Challenge: Create a 50 MB self-contained CLI tool.

Item 43: Use jdeps to Analyze Dependencies

Why it matters: Helps modularize monoliths. Challenge: Run jdeps --summary on a legacy jar.

Item 44: Use jmod for Module Packaging

Why it matters: Enables distribution as modular runtimes. Challenge: Package and inspect a module file.

Item 45: Learn JUnit 5 + Virtual Threads Testing

Why it matters: Verify concurrency behavior correctly. Challenge: Write concurrent tests using Loom executors.

Item 46: Adopt Build Tools Supporting JDK 21

Why it matters: Ensure Gradle/Maven compatibility. Challenge: Upgrade toolchains to Java 21 target.

Item 47: Use Java Flight Recorder (JFR) Events in Production

Why it matters: Lightweight continuous monitoring. Challenge: Capture async profiler traces during peak load.

Item 48: Understand Module Graphs

Why it matters: Visualize dependencies between modules. Challenge: Generate and interpret a module graph via IDE.

Item 49: Enable Preview Features in IDEs

Why it matters: Needed for String Templates or Scoped Values. Challenge: Configure IntelliJ or VS Code for preview flags.

Item 50: Document New APIs with Javadoc Tags

Why it matters: Maintain clarity across language evolution. Challenge: Annotate which JEP introduced each API.

Advanced Concurrency, Parallelism & Synchronization

Item 51: Use StructuredTaskScope for Parent–Child Task Coordination (JEP 453)

Leverage StructuredTaskScope to supervise concurrent subtasks. Why it matters: Simplifies cancellation, exception aggregation, and lifecycle. Challenge: Implement a service calling 3 APIs concurrently, failing fast on error. JEP 453

Item 52: Prefer CompletableFuture with Virtual Threads

Combine structured concurrency with async pipelines. Why it matters: Integrates legacy async codebases with Loom. Challenge: Wrap blocking calls in CompletableFuture executed by virtual threads.

Item 53: Use ReentrantLock Fairness Wisely

Why it matters: Fair locks prevent starvation but reduce throughput. Challenge: Benchmark fair vs non-fair ReentrantLock under contention.

Item 54: Experiment with StampedLock

Why it matters: Offers optimistic reads improving performance on read-heavy workloads. Challenge: Replace ReentrantReadWriteLock with StampedLock in a cache.

Item 55: Implement Thread-Safe Lazy Initialization

Why it matters: Reduces synchronization overhead. Challenge: Use Holder idiom or AtomicReference for on-demand singleton creation.

Item 56: Use Structured Concurrency for Request Timeouts

Why it matters: Centralized timeout handling reduces complexity. Challenge: Add per-request timeout with StructuredTaskScope::shutdown.

Item 57: Avoid Blocking Virtual Threads with Synchronous IO APIs

Why it matters: Some legacy JDBC drivers block OS threads internally. Challenge: Identify such cases and switch to Loom-friendly drivers.

Item 58: Monitor Virtual Thread States

Why it matters: Debugging thousands of fibers requires tooling awareness. Challenge: Use jcmd Thread.print and visualize Loom thread hierarchies.

Item 59: Mix Loom and Reactor in Controlled Way

Why it matters: Transition period will require hybrid designs. Challenge: Implement a reactive adapter invoking blocking virtual thread APIs.

Item 60: Apply Scoped Values for MDC-like Logging Contexts (JEP 429)

Why it matters: Replaces ThreadLocal for correlation IDs in distributed logs. Challenge: Pass trace IDs through nested virtual threads using scoped values. JEP 429

Memory Management, GC and Performance Tuning

Item 61: Enable Generational ZGC (JEP 439)

Why it matters: Combines low pause times with generational heuristics. Challenge: Compare throughput vs standard ZGC on long-lived workloads. JEP 439

Item 62: Analyze Heap Usage with jmap and jcmd GC.heap_info

Why it matters: Identifies leaks in new thread-rich apps. Challenge: Capture heap histograms before and after traffic spikes.

Item 63: Profile Allocation Hotspots Using JFR Events

Why it matters: Allocation pressure causes hidden GC churn. Challenge: Record 30 s JFR profile, detect high-frequency object types.

Item 64: Measure Loom Stack Overheads

Why it matters: Each virtual thread allocates stack segments dynamically. Challenge: Spawn 1 M virtual threads and observe RSS growth.

Item 65: Explore Compact Object Headers (JEP 450)

Why it matters: Reduces memory overhead per object. Challenge: Enable -XX:+UseCompactObjectHeaders and inspect with jol-cli. JEP 450

Item 66: Benchmark Stream vs Loop Performance

Why it matters: Streams add abstraction overhead; measure trade-offs. Challenge: Use JMH to benchmark 10^6 element processing.

Item 67: Understand Escape Analysis

Why it matters: The JVM may allocate objects on stack if non-escaping. Challenge: Verify with -XX:+PrintEscapeAnalysis flags.

Item 68: Use G1 Mixed GC Tuning

Why it matters: Controls pause predictability for moderate heaps. Challenge: Tune -XX:MaxGCPauseMillis and observe GC logs.

Item 69: Enable String Deduplication in G1

Why it matters: Frees memory when many duplicate strings exist. Challenge: Activate -XX:+UseStringDeduplication and track reclaimed memory.

Item 70: Use Native Memory Tracking (NMT)

Why it matters: Monitors off-heap allocations from FFM or buffers. Challenge: Run with -XX:NativeMemoryTracking=detail and parse output.

Language Deep Dives and Best Practices

Item 71: Use Records as Map Keys

Why it matters: Records generate stable hashCode and equals. Challenge: Replace composite key classes with records in caching layer.

Item 72: Combine Sealed and Record Types

Why it matters: Perfect for algebraic data modeling. Challenge: Model Shape as a sealed interface with record variants.

Item 73: Explore Pattern Matching in if-Statements (JEP 394)

Why it matters: Enables concise and type-safe conditions. Challenge: Replace instanceof casting with pattern binding. JEP 394

Item 74: Implement Nested Record Patterns

Why it matters: Destructure complex record graphs inline. Challenge: Decompose nested record structures with one pattern.

Item 75: Test Switch Patterns with Enums

Why it matters: Compile-time exhaustiveness checking improves safety. Challenge: Create exhaustive switch over enum variants with default elimination.

Item 76: Use var with Care in Lambdas

Why it matters: Enables annotations but can obscure types. Challenge: Annotate lambda parameters with @Nonnull using var.

Item 77: Write Null-Safe Code with Pattern Guards

Why it matters: Prevents NPEs in switch branches. Challenge: Use when clauses to guard against null inputs.

Item 78: Explore String Template Processors (Preview JEP 430)

Why it matters: You can build custom templating logic. Challenge: Implement a safe HTML escaping template processor. JEP 430

Item 79: Integrate Text Blocks into Logging

Why it matters: Simplifies multi-line formatting. Challenge: Format structured JSON logs using text blocks.

Item 80: Migrate Utility Classes to Records with Static Methods

Why it matters: Encourages immutability even in helpers. Challenge: Refactor configuration value objects to records.

Networking, IO and Security

Item 81: Use Virtual Threads for HTTP Clients

Why it matters: Greatly increases concurrency for blocking IO. Challenge: Create a virtual-thread-based HTTP downloader.

Item 82: Evaluate HTTP/2 Performance in Java 21

Why it matters: Built-in HttpClient supports multiplexing. Challenge: Measure difference vs Apache HttpClient under load.

Item 83: Test SSLSession Reuse and TLS 1.3 Performance

Why it matters: Security and performance balance is critical. Challenge: Benchmark handshake times using JDK 21 default cipher suites.

Item 84: Use Files.mismatch() for Fast Comparisons

Why it matters: Efficient binary comparison built in. Challenge: Write a deduplication tool for backups.

Item 85: Explore SocketChannel with Virtual Threads

Why it matters: Combines NIO scalability with Loom simplicity. Challenge: Build simple chat server using blocking APIs in virtual threads.

Item 86: Use AsynchronousFileChannel for High I/O Loads

Why it matters: Prevents thread blocking on large reads/writes. Challenge: Benchmark parallel file processing pipelines.

Item 87: Secure Random Generation with SecureRandom.getInstanceStrong()

Why it matters: Cryptographically strong RNGs prevent vulnerabilities. Challenge: Generate secure tokens for authentication system.

Item 88: Validate File Permissions with PosixFileAttributes

Why it matters: Enforces least privilege model. Challenge: Scan and fix incorrect file permission bits.

Item 89: Use ProcessHandle API for System Management

Why it matters: Monitor and control OS processes safely. Challenge: Spawn subprocesses and capture CPU usage.

Item 90: Integrate Loom with Asynchronous DB Drivers

Why it matters: Evaluate JDBC → R2DBC or Loom hybrids. Challenge: Test latency between virtual thread JDBC vs R2DBC queries.

Testing, Tooling, and Migration

Item 91: Use JUnit Parallel Execution with Virtual Threads

Why it matters: Tests scale without thread-pool exhaustion. Challenge: Enable virtual-thread test executor in JUnit 5.

Item 92: Measure Coverage with Jacoco on JDK 21

Why it matters: Ensure tooling compatibility post-migration. Challenge: Configure Jacoco for preview-feature modules.

Item 93: Detect Deprecated APIs via jdeprscan

Why it matters: Prepares for JDK 25 upgrades. Challenge: Run jdeprscan and document replacements.

Item 94: Automate Builds with Gradle 8.x and JDK 21 Toolchain

Why it matters: Uses javaToolchains for consistent CI builds. Challenge: Define multiple Java versions in Gradle build.

Item 95: Run Static Analysis with ErrorProne

Why it matters: Detects common Loom misuses early. Challenge: Enable ErrorProne in build and fix reported issues.

Item 96: Use JMH Microbenchmarks for Loom

Why it matters: Empirically verify performance claims. Challenge: Benchmark thread-per-task vs virtual thread per task.

Item 97: Implement Custom JFR Event for Business Metrics

Why it matters: Expose domain-specific metrics in Flight Recorder. Challenge: Add JFR annotations to capture transaction latency.

Item 98: Validate Compatibility with Dockerized Runtimes

Why it matters: Ensures JVM resource awareness in containers. Challenge: Run Java 21 in Docker and observe cgroup metrics.

Item 99: Document Migration Steps from Java 17 → 21

Why it matters: Smooth upgrades minimize risk. Challenge: Write migration checklist including module and API updates.

Item 100: Teach and Share Loom Best Practices

Why it matters: Knowledge transfer solidifies expertise. Challenge: Conduct an internal workshop showcasing Java 21 concurrency improvements.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages