Unravel › Java concepts › Learning paths
Java learning paths
Each path orders the concepts so that every idea builds on the ones before it. Open a concept, read it, and mark it as learned; your progress is saved only in this browser. Then paste your own code into Unravel to see the ideas at work.
Kafka for Java developers
From "what is a topic" to consumer groups, offsets and delivery guarantees.
0 of 9 learned
- Kafka topics, partitions and events
Kafka is a durable log of events - Serializers and deserializers
Kafka stores only bytes - Kafka producer
A producer sends events to a topic - Kafka consumer and the poll loop
A consumer reads events from a topic in a loop - Consumer groups
A consumer group is a set of consumers that share one job - Offsets and commits
An offset is a record's position in a partition - Rebalancing
A rebalance is Kafka reshuffling which consumer owns which partition, triggered by a member joining, leaving, crashing or being too slow - Spring Kafka @KafkaListener
Spring Kafka runs the poll loop for you - Retries and dead-letter topics
When a record cannot be processed, a Kafka consumer must not block forever and must not silently drop it
How a Spring request really works
Beans, proxies, controllers, JSON, transactions and the database behind them.
0 of 11 learned
- Spring beans and dependency injection
Spring creates your objects (beans) and hands each one the other objects it needs, so classes declare their dependencies and never build them with new - Spring proxies (how annotations work)
Annotations like @Transactional, @Async and @Cacheable work through a proxy: Spring wraps your bean in a stand-in object that adds behaviour before and after your method - Jackson JSON
Jackson converts between Java objects and JSON - Spring REST controllers
A controller maps HTTP requests to Java methods - Bean validation (@Valid)
Bean validation lets you declare rules on fields (@NotBlank, @Size(max = 50), @Email) and have the framework check them - Spring Security basics
Spring Security puts a chain of filters in front of your application - @Transactional
@Transactional makes a method run inside a database transaction: all its database changes commit together if it finishes normally and are rolled back together if it throws - JPA entities
An entity is a Java class mapped to a database table: each instance is a row, each field a column - Lazy loading and the N+1 query problem
Relations between entities are often loaded lazily, one extra query on first access - Spring Data repositories
A Spring Data repository is an interface only - Spring caching
@Cacheable stores a method's result under a key built from its arguments
Background work in Spring
Scheduled jobs, async methods, events and configuration without surprises.
0 of 7 learned
- Spring beans and dependency injection
Spring creates your objects (beans) and hands each one the other objects it needs, so classes declare their dependencies and never build them with new - Spring configuration properties
Spring reads settings from application.yml, environment variables and command-line flags, and injects them into beans with @Value or @ConfigurationProperties, so behaviour changes per environment without rebuilding - @Scheduled jobs
@Scheduled runs a method repeatedly on a timer: at a fixed rate, with a fixed delay between runs, or on a cron schedule - Quartz scheduler
Quartz is a job scheduling library - Executors and thread pools
An executor runs tasks on a reusable pool of threads - @Async
@Async makes a call return immediately while the method body runs on another thread from a pool - Spring application events
Events let one bean announce "something happened" without knowing who cares
Modern Java: lambdas and streams
Interfaces, lambdas, generics, collections, streams and Optional.
0 of 9 learned
- Interfaces, inheritance and polymorphism
An interface is a contract of methods that classes can promise to provide - Lambdas and functional interfaces
A lambda is a short, nameless function you can pass around: x -> x * 2 - Method references
A method reference such as String::valueOf is a shorthand lambda that just calls an existing method: x -> String.valueOf(x) - Generics
Generics put a type in angle brackets, as in List<String>, so the compiler checks what a container holds and you need no casts - Collections: List, Set, Map
Collections hold groups of objects - Streams
A stream is a pipeline over a sequence of values: start from a source, chain steps such as filter and map, and finish with a terminal step such as collect - Optional and null safety
Optional<T> is a box that holds a value or nothing - StringBuilder and string building
Strings in Java never change - Regular expressions
A regular expression describes a pattern of text
Concurrency fundamentals
Threads, locks, atomics, executors, CompletableFuture and concurrent collections.
0 of 7 learned
- Threads and shared state
A thread is an independent path of execution - synchronized and locks
synchronized lets only one thread at a time run a block of code on a given lock object, protecting shared data from interleaved access - volatile and atomic classes
Atomic classes update a single value as one indivisible step without a lock - ReentrantLock and ReadWriteLock
The java.util.concurrent.locks classes are explicit versions of synchronized with extras: try without waiting, time out, separate read and write access, and more than one condition - Executors and thread pools
An executor runs tasks on a reusable pool of threads - CompletableFuture
CompletableFuture represents a result that will arrive later - Concurrent collections
Concurrent collections are safe to share between threads
Reliable code
Exceptions, resource handling, logging and tests.
0 of 6 learned
- Exceptions: try, catch, throw
An exception is how Java reports that something went wrong - try-with-resources
try-with-resources opens a resource in the parentheses after try and closes it automatically when the block ends, normally or by exception, so files, connections and streams are never leaked - Logging with SLF4J
A logger writes diagnostic messages at a level (trace, debug, info, warn, error) - Retry and circuit breaker
Remote calls fail for short moments - JUnit tests
A JUnit test is a method annotated with @Test that sets something up, runs the code under test and asserts the expected result - Mockito mocks
Mockito creates fake versions of a class's collaborators so a test can control what they return and check how they were used, without a real database or network
Modeling data in modern Java
Records, enums, switch expressions, dates and exact decimals.
0 of 7 learned
- Lombok annotations
Lombok writes boilerplate for you at compile time - Records
A record is a compact class for plain data: you list the fields once and Java generates the constructor, getters, equals, hashCode and toString - equals() and hashCode()
equals says when two objects count as the same; hashCode gives a number used to file objects into hash tables - Enums
An enum is a fixed set of named constants, such as order statuses - Switch expressions and pattern matching
Modern switch can be an expression that produces a value, with arrow cases that do not fall through - java.time dates and times
The java.time classes separate a point on the timeline (Instant), a calendar date or time without a zone (LocalDate, LocalDateTime) and a zoned moment (ZonedDateTime) - BigDecimal and money
BigDecimal stores decimal numbers exactly, so it is used for money
Inside Spring Boot
How Boot configures itself, how beans live and die, filters, error handling and operations.
0 of 9 learned
- Spring beans and dependency injection
Spring creates your objects (beans) and hands each one the other objects it needs, so classes declare their dependencies and never build them with new - Spring Boot auto-configuration and starters
Spring Boot looks at the libraries on your classpath and your properties, and configures sensible beans for you (a web server, a data source, a JSON mapper) unless you define your own - @Configuration, @Bean and bean wiring
A @Configuration class is a recipe for creating beans in plain Java - Bean lifecycle and startup hooks
Spring runs code at fixed moments in a bean life: right after it is built and wired, when the application is ready, and just before it is thrown away - Writing aspects (@Aspect, pointcuts, advice)
An aspect is code that you attach to many methods at once (timing, audit logging, permission checks) without editing them - Servlets, filters and interceptors
Every Java web request passes through the servlet layer - Central error handling and ProblemDetail
Instead of try/catch in every controller, one advice class maps each exception type to an HTTP status and a consistent error body, so clients always get the same shape of error - Spring Boot Actuator and health checks
Actuator adds operational endpoints to a running Spring Boot app (health, metrics, environment, thread dump) - Metrics with Micrometer
Micrometer is the metrics facade of Spring Boot
JPA and Hibernate in depth
Relationships, the persistence context, queries, locking, transactions and schema changes.
0 of 12 learned
- JPA entities
An entity is a Java class mapped to a database table: each instance is a row, each field a column - JPA relationships, cascade and orphan removal
Relationship mappings tell JPA how tables are linked - Lazy loading and the N+1 query problem
Relations between entities are often loaded lazily, one extra query on first access - Persistence context, flush and dirty checking
Inside a transaction, JPA keeps every entity it has loaded in a first-level cache and watches it for changes - JPQL, native queries and the Criteria API
JPQL is SQL written against your entity classes and fields instead of tables and columns - Dynamic queries (Specifications, Example, Querydsl)
When search filters are optional (name, status, date range), you cannot write one fixed query method - Optimistic and pessimistic locking
Two users editing the same record at the same time is the lost-update problem - Transaction propagation and isolation
Propagation decides what happens when a transactional method calls another transactional method (join the current transaction or start a new one) - JPA inheritance mapping
Object models have inheritance (a Payment is a CardPayment or a BankTransfer) but tables do not - Auditing, lifecycle callbacks and soft delete
Many tables need "who and when": created and modified timestamps, the user who did it, and sometimes a flag instead of real deletion - Database migrations (Flyway, Liquibase)
A migration tool applies numbered SQL scripts to the database in order and remembers which ones ran, so every environment, from a laptop to production, ends up with exactly the same schema - Connection pools (HikariCP)
Opening a database connection is slow, so applications keep a small pool of open connections and lend them out
Security for backend developers
Filter chain, tokens, OAuth2, CORS and CSRF, password storage and cryptography.
0 of 10 learned
- Spring Security basics
Spring Security puts a chain of filters in front of your application - Spring Security filter chain and authorization rules
Spring Security is a chain of servlet filters in front of your controllers - JSON Web Tokens (JWT)
A JWT is a signed token that carries claims (who the user is, when it expires, what roles they have) - OAuth 2.0 and OpenID Connect login
OAuth 2.0 lets users sign in or let one service call another without sharing a password - CORS and CSRF protection
CORS decides which web pages from other origins may call your API from a browser - Password hashing (BCrypt, Argon2, PBKDF2)
Passwords must be stored as slow, salted hashes so that a stolen database does not reveal them - Hashes, HMAC and secure random
A hash turns data of any size into a fixed fingerprint; an HMAC adds a secret key so that only parties who know it can create the fingerprint - Symmetric encryption (AES-GCM) and key handling
Encryption makes data unreadable without a key - TLS, keystores and certificates
TLS encrypts connections and proves the identity of the server (and optionally the client) with certificates - LDAP and directory lookups
LDAP (and Active Directory) is the company address book that stores users, groups and credentials
Kafka beyond the basics
Streams, transactions, schemas, Connect and testing.
0 of 6 learned
- Kafka producer
A producer sends events to a topic - Kafka idempotent producer and transactions
Two features make Kafka writes safer: the idempotent producer removes duplicates caused by retries, and transactions write to several partitions and commit consumer offsets all-or-nothing - Kafka Streams
Kafka Streams is a library for processing topics as continuous streams inside your own application: filter, transform, join and aggregate events, with state kept locally and backed up to Kafka - Schema Registry, Avro and Protobuf
A schema registry stores the structure of messages (Avro, Protobuf or JSON Schema) and checks that producers and consumers change it compatibly - Kafka Connect connectors
Kafka Connect moves data between Kafka and other systems (databases, search, object storage) using ready-made connectors that you configure instead of coding consumers and producers - Testing Kafka code
Kafka code is tested at three levels: unit tests with mock producers and consumers, topology tests for Kafka Streams without a broker, and integration tests against a real broker started by the test (embedded or in a container)
Reliable messaging and distributed patterns
Brokers, outbox, idempotency, sagas and event sourcing.
0 of 7 learned
- RabbitMQ and AMQP messaging
RabbitMQ is a message broker - JMS and ActiveMQ messaging
JMS is the standard Java API for message brokers (ActiveMQ, IBM MQ, Artemis) - AWS SQS and SNS messaging
SQS is a managed queue and SNS is a managed publish-subscribe topic - Idempotency and duplicate handling
Networks and message brokers repeat things: a client retries, a broker redelivers - Transactional outbox pattern
Saving to the database and publishing a message are two separate actions, and a crash between them loses or invents events - Sagas and distributed transactions
A business process that spans several services cannot use one database transaction - CQRS and event sourcing
CQRS separates writing (commands that change state) from reading (queries over a shape built for the screen)
Cloud-native Java
Containers, credentials, cloud SDKs, serverless, tracing, logs and gateways.
0 of 11 learned
- Containers and Kubernetes in Java code
Production Java services run in containers on Kubernetes, and that shapes the code: configuration comes from environment variables, the app must start and stop quickly and gracefully, and sometimes the code talks to the cluster API itself - Cloud credentials and secrets management
Code that calls cloud services needs credentials, and database passwords and API keys need a safe home - Object storage SDKs (S3, Azure Blob, GCS)
Object storage (Amazon S3, Azure Blob Storage, Google Cloud Storage) keeps files as objects in buckets, addressed by a key - DynamoDB access
DynamoDB is a managed key-value and document database that stays fast at any size - Azure Service Bus, Event Hubs and Google Pub/Sub
Azure and Google offer managed brokers (Service Bus and Event Hubs; Pub/Sub) - Serverless function handlers (AWS Lambda, Azure, GCP)
A serverless function is one handler method that the cloud runs on demand, in response to a request, a queue message, a file upload or a schedule - Distributed tracing (OpenTelemetry)
A single user request can touch ten services - Structured logging and correlation ids (MDC)
In a busy service, plain log lines from different requests are mixed together - Service discovery and central config (Spring Cloud)
In a microservice system, instances start and stop all the time - API gateways (Spring Cloud Gateway)
A gateway is the single front door of a set of microservices - Rate limiting and throttling
A rate limiter caps how many requests a client or operation may make per time window
Building and documenting APIs
REST, OpenAPI, GraphQL, gRPC, streaming and client generation.
0 of 12 learned
- Spring REST controllers
A controller maps HTTP requests to Java methods - OpenAPI and Swagger documentation
OpenAPI is a machine-readable description of a REST API - Custom Jackson serialization and modules
When default JSON mapping is not enough (dates in a special format, money as a string, hiding fields per audience, circular references), Jackson can be tuned with annotations, features and custom serializers registered in modules - GraphQL servers
GraphQL lets the client ask for exactly the fields it needs in one request - gRPC services and clients
gRPC is a fast, typed way for services to call each other - Declarative HTTP clients (Feign, HTTP interfaces)
You write a Java interface describing a remote REST API with annotations, and the framework generates the HTTP client behind it - Streaming responses and Server-Sent Events
Instead of answering once, a streaming endpoint keeps the HTTP connection open and sends several pieces over time: progress updates, live events, or a big file written as it is generated - WebSockets and STOMP messaging
A WebSocket is a long-lived two-way connection between browser and server, so either side can send at any time - File upload and download
Uploads arrive as multipart form data and downloads are streams with a Content-Disposition header - XML, YAML, Gson and Protobuf
Enterprise systems exchange data in many formats besides JSON: XML (SOAP, legacy and government feeds), YAML configuration, Gson in older code, and Protobuf for compact internal messages - Java serialization and its risks
Java can turn an object graph into bytes (Serializable) and back - SOAP and JAX-WS web services
SOAP is an older, XML-based way for systems to call each other, still common in banking, insurance and government
Jakarta EE and other frameworks
CDI, EJB, JAX-RS, Quarkus, Micronaut and Vert.x.
0 of 6 learned
- CDI: contexts and dependency injection (Jakarta EE)
CDI is the standard dependency injection of Jakarta EE (and Quarkus) - EJB session beans and container services
Enterprise JavaBeans are the original Java EE components - JAX-RS (Jakarta REST) resources
JAX-RS, now Jakarta REST, is the standard annotation model for REST in Java EE and Jakarta EE servers and in Quarkus - Quarkus applications
Quarkus is a Java framework designed for containers and fast startup - Micronaut applications
Micronaut is a JVM framework with dependency injection and AOP done at compile time instead of runtime reflection - Vert.x verticles and the event loop
Vert.x is a toolkit for non-blocking applications on the JVM
Testing enterprise code
JUnit and Mockito in depth, Spring slices, HTTP tests, containers and fake services.
0 of 9 learned
- JUnit tests
A JUnit test is a method annotated with @Test that sets something up, runs the code under test and asserts the expected result - Advanced JUnit 5 and async assertions
Beyond simple @Test methods, JUnit 5 supports parameterised tests, nested test groups, temporary directories, conditional execution and custom extensions - Mockito mocks
Mockito creates fake versions of a class's collaborators so a test can control what they return and check how they were used, without a real database or network - Advanced Mockito (matchers, captors, static mocks)
Mockito does more than when(...).thenReturn(...) - Spring Boot test slices and test configuration
A full @SpringBootTest starts the whole application, which is slow - Testing HTTP endpoints (MockMvc, WebTestClient, REST Assured)
These tools call your endpoints from a test and check status, headers and JSON body - Testcontainers (real databases and brokers in tests)
Testcontainers starts real services (PostgreSQL, Kafka, Redis, Elasticsearch) in Docker for the duration of a test - Faking remote services (WireMock, MockWebServer, Pact)
To test code that calls another service, you stand up a fake HTTP server that returns the answers you script: successes, errors, slow responses and broken connections - Testing Kafka code
Kafka code is tested at three levels: unit tests with mock producers and consumers, topology tests for Kafka Streams without a broker, and integration tests against a real broker started by the test (embedded or in a container)
Scheduled jobs, batch and integration
Cron, Quartz, cluster locking, Spring Batch, files and integration flows.
0 of 10 learned
- @Scheduled jobs
@Scheduled runs a method repeatedly on a timer: at a fixed rate, with a fixed delay between runs, or on a cron schedule - Cron expressions in Java
A cron expression is a compact line that says when something repeats, such as every weekday at 02:30 - Quartz scheduler
Quartz is a job scheduling library - Distributed locks and job locking (ShedLock)
When several copies of an application run at once, an ordinary synchronized or ReentrantLock only protects one copy - Spring Batch jobs, steps and chunks
Spring Batch runs big, restartable jobs: read many records, process each, write them in chunks inside transactions, and remember how far it got so a failed run can resume - CSV and Excel file processing
Business systems constantly import and export CSV and Excel files - Spring Integration (channels and flows)
Spring Integration implements classic enterprise integration patterns in-process: messages travel over channels, and small components filter, transform, route, split and aggregate them - Apache Camel integration routes
Apache Camel connects systems with routes: take a message from one endpoint (file, queue, HTTP, database), transform and route it, and deliver it to another - SFTP and file transfer clients
Many partners still exchange files over SFTP or FTP - Sending email (JavaMail, Spring Mail)
Applications send email for receipts, resets and alerts through an SMTP server
Data stores beyond SQL
Redis, local caches, MongoDB, Elasticsearch, Cassandra, DynamoDB and SQL mappers.
0 of 8 learned
- Redis clients and data structures
Redis is an in-memory data store with simple structures (strings, hashes, lists, sets, sorted sets) - In-memory caches (Caffeine, Guava, Ehcache)
A local cache keeps results of expensive work (a database read, a remote call) in memory next to your code - MongoDB documents and queries
MongoDB stores JSON-like documents in collections instead of rows in tables - Elasticsearch and OpenSearch search
Elasticsearch is a search engine built on inverted indexes - Cassandra and wide-column modelling
Cassandra spreads data over many nodes by a partition key and is built for huge write volumes and predictable reads - DynamoDB access
DynamoDB is a managed key-value and document database that stays fast at any size - SQL mappers and builders (MyBatis, jOOQ)
MyBatis and jOOQ sit between raw JDBC and a full ORM: you control the SQL, and the library handles parameters, result mapping and (in jOOQ) type-safe query building - JDBC transactions, batching and JdbcTemplate mapping
By default each JDBC statement commits alone
Reactive Java
Reactor, WebFlux, reactive data access and the event loop.
0 of 5 learned
- Lambdas and functional interfaces
A lambda is a short, nameless function you can pass around: x -> x * 2 - Reactive programming (Reactor Mono and Flux)
Reactive code describes a pipeline for data that arrives over time - Reactive data access (R2DBC and reactive repositories)
Reactive repositories return Mono and Flux instead of blocking until the database answers, so a few threads can serve many concurrent requests while the database is working - API gateways (Spring Cloud Gateway)
A gateway is the single front door of a set of microservices - Vert.x verticles and the event loop
Vert.x is a toolkit for non-blocking applications on the JVM
Structuring an enterprise service
Layers, ports and adapters, DTOs and mapping, transactions and safe messaging.
0 of 6 learned
- Spring beans and dependency injection
Spring creates your objects (beans) and hands each one the other objects it needs, so classes declare their dependencies and never build them with new - Layered and hexagonal architecture
Enterprise code is usually split into layers (controller, service, repository) so that each class has one job - DTOs and object mapping (MapStruct, ModelMapper)
A DTO (data transfer object) is a plain class that carries data across a boundary (API, message) and is shaped for that boundary - @Transactional
@Transactional makes a method run inside a database transaction: all its database changes commit together if it finishes normally and are rolled back together if it throws - Idempotency and duplicate handling
Networks and message brokers repeat things: a client retries, a broker redelivers - Transactional outbox pattern
Saving to the database and publishing a message are two separate actions, and a crash between them loses or invents events
Object-oriented Java in depth
Constructors, inheritance, abstract and nested classes, static and final, copying, annotations and reflection.
0 of 15 learned
- Classes, objects and constructors
A class is a blueprint; an object is one thing built from it with new - Inheritance, extends and super
class Dog extends Animal makes Dog a specialised Animal: it inherits the fields and methods and may replace (override) some of them - Abstract classes
An abstract class is an unfinished class: it can hold shared code and state, and declares abstract methods that every concrete subclass must fill in - Default and static interface methods
An interface method marked default has a body, so implementing classes get it for free and may override it - Nested and inner classes
A class declared inside another class - Anonymous classes
An anonymous class creates and defines a one-off subclass or implementation right where it is used: new Runnable() { public void run() { .. - static and final members
static means "belongs to the class, not to any object": one shared copy - Initialisation order and init blocks
A static { .. - Immutability and final classes
An immutable object never changes after construction - The Object class: toString, getClass, hashCode
Every class extends Object and inherits toString, equals, hashCode and getClass - Copying objects: clone and copy constructors
Assigning an object (b = a) copies the reference, not the object - Enums with fields and behaviour
A Java enum is a full class with a fixed set of instances - Custom annotations
An annotation is a label you attach to code (@Deprecated, @Test) - Reflection
Reflection lets code look at classes, methods and fields by name at run time, and call or change them, without knowing them at compile time - Dynamic proxies
Proxy.newProxyInstance builds an object at run time that implements an interface and sends every call to one InvocationHandler
Modern Java syntax
var, text blocks, varargs, sealed types, pattern matching, wildcards and sorting rules.
0 of 8 learned
- Loops, labels and do-while
break leaves the nearest loop, continue skips to the next round, and a label (outer:) lets either one target an outer loop - var and type inference
var lets the compiler work out the type of a local variable from the right-hand side: var users = new ArrayList<User>(); - Text blocks
A text block is a multi-line string literal between triple quotes (""") - Varargs
A parameter declared String.. - Sealed classes and interfaces
sealed restricts who may extend or implement a type: sealed interface Shape permits Circle, Square - Pattern matching with instanceof
if (o instanceof String s) tests the type and gives you a ready-cast variable s in one step - Wildcards and bounded generics
List<? extends Number> means "a list of some kind of Number, I do not know which"; List<? super Integer> means "a list that accepts Integers". Bounds like <T extends Comparable<T>> limit what a type parameter may be - Comparable and Comparator
Sorting needs a rule for "which comes first"
Text, numbers and arrays
Strings, formatting, characters, floating point, overflow, boxing, Math, randomness, arrays and bits.
0 of 11 learned
- Strings: immutability, equality, common methods
A String is an immutable piece of text: no method ever changes it, every "change" returns a new String - Formatting text and numbers
String.format("%s has %d items (%.2f%%)", name, n, pct) builds text from a template with placeholders - Characters, Unicode and encodings
A char is a 16-bit UTF-16 unit, not always a whole visible character - Primitive types and floating point
Java has eight primitive types (byte short int long float double char boolean) - Integer overflow and exact arithmetic
An int that goes past 2,147,483,647 does not fail: it silently wraps around to a large negative number - Autoboxing and wrapper types
Each primitive has an object twin (int and Integer) - Math and number utilities
Math is a toolbox of static methods: max, min, abs, pow, sqrt, round, floor, ceil, trigonometry and logarithms - Random numbers and UUIDs
Random produces repeatable pseudo-random numbers from a seed, SecureRandom produces unpredictable ones for security, and UUID.randomUUID() creates a practically unique 128-bit identifier - Arrays and the Arrays utilities
An array is a fixed-size row of values of one type, indexed from 0: int[] a = new int[5] - Bitwise operators and flags
Bitwise operators work on the individual bits of a number: & and, | or, ^ xor, ~ not, << and >> shift - Hashing, Base64 and encryption
MessageDigest hashes data (SHA-256), Mac signs it with a secret (HMAC), Cipher encrypts it, and Base64 turns bytes into safe text
Collections in depth
How lists, maps, sets, queues and iterators work, and how to avoid their classic traps.
0 of 11 learned
- ArrayList vs LinkedList
ArrayList keeps its elements in a resizable array: fast to read by position, slow to insert in the middle - How HashMap works
A HashMap stores each entry in a bucket chosen by the key's hashCode() - Map idioms: merge, compute, entrySet
A handful of Map methods replace the clumsy "check, get, put" dance: merge for counting, computeIfAbsent for grouping, getOrDefault for lookups with a default, and entrySet for looping over keys and values together - Sets: HashSet, LinkedHashSet, EnumSet
A Set holds each element at most once - TreeMap, TreeSet and sorted collections
TreeMap and TreeSet keep their elements sorted all the time and can answer range questions: the first key, the nearest key below or above a value, everything between two keys - Queue, Deque and Stack
A queue is first-in-first-out (a line at the shop), a stack is last-in-first-out (a pile of plates) - PriorityQueue and heaps
A PriorityQueue always hands out the smallest element first (or the largest with a reversed comparator), whatever order you added them in - Iterator and Iterable
An Iterator walks through a collection one element at a time (hasNext, next, remove) - ConcurrentModificationException
This exception means a collection was changed while a loop was going through it - The Collections utility class
Collections has static helpers for lists and sets: sort, reverse, shuffle, max, min, frequency, swap, plus wrappers that make a collection read-only, synchronized or empty - Legacy collections: Vector, Hashtable, Enumeration
Vector, Hashtable, Stack, Enumeration and StringTokenizer date from Java 1.0
Streams in depth
Stream operations, collectors and parallel streams.
0 of 3 learned
- Stream operations in depth
Intermediate steps (filter, map, flatMap, sorted, distinct, limit) shape the data; terminal steps (reduce, collect, count, anyMatch, findFirst) produce the answer - Collectors: groupingBy, toMap, joining
A Collector decides what a stream becomes at the end: a list, a map, a group per key, a count, a joined string - Parallel streams
list.parallelStream() splits the work across several threads of the common fork-join pool
I/O, networking and time
Streams, files, serialization, sockets, XML and JSON, configuration, and dates with time zones.
0 of 12 learned
- Byte streams, readers and writers
Java has two families for moving data: byte streams (InputStream, OutputStream) for raw bytes, and character readers and writers (Reader, Writer) that decode bytes to text with a charset - NIO.2: Path and Files in practice
Path describes a location and Files does the work: read, write, copy, move, list and delete - Java serialization
Serialization turns an object graph into bytes (ObjectOutputStream) and back (ObjectInputStream) - ZIP and GZIP compression
GZIPOutputStream compresses a single stream; ZipOutputStream bundles many named entries into one archive - Sockets, URLs and networking
A Socket is one end of a TCP connection: you write bytes in and read bytes out - The built-in HTTP server
com.sun.net.httpserver.HttpServer is a tiny web server inside the JDK - XML parsing: DOM, SAX, StAX
Java reads XML three ways: DOM loads the whole document into a tree you can query, SAX and StAX stream through it event by event, and JAXB or Jackson XML map elements onto classes - Gson and other JSON APIs
Gson, org.json and JSON-B are other ways to turn JSON into Java objects and back - Properties files, Locale and resource bundles
Properties loads key=value text files into a map - Formatting, parsing and date arithmetic
DateTimeFormatter.ofPattern("dd.MM.yyyy") turns dates into text and back, and methods like plusDays, isBefore and ChronoUnit.DAYS.between do date arithmetic without the pitfalls of old Date code - Time zones, DST and Instant
An Instant is one exact moment on the global timeline - Legacy Date, Calendar and SimpleDateFormat
java.util.Date, Calendar and SimpleDateFormat are the pre-Java-8 date classes
Errors, logging and tests in depth
Custom exceptions, causes, common errors, preconditions, logging APIs and modern test tools.
0 of 9 learned
- The exceptions you meet every day
A short list of exceptions causes most production errors: NullPointerException, IndexOutOfBoundsException, ClassCastException, NumberFormatException, IllegalArgumentException, IllegalStateException, UnsupportedOperationException, StackOverflowError and OutOfMemoryError - Custom exceptions: checked vs unchecked
A checked exception (extends Exception) must be caught or declared with throws; an unchecked one (extends RuntimeException) need not - Exception causes and stack traces
When one exception is caused by another, pass the original as the "cause": throw new ServiceException("save failed", e) - Defensive checks: assert and preconditions
Fail early and loudly: check arguments at the start of a method (Objects.requireNonNull, if (x < 0) throw new IllegalArgumentException(...)) - Other logging APIs: JUL, Log4j, System.out
SLF4J is the usual facade, but code also uses java.util.logging (JUL, built into the JDK, with levels SEVERE to FINEST), Log4j 2 (LogManager.getLogger), Commons Logging, or plain System.out - JUnit 5: parameterized tests and lifecycle
A @ParameterizedTest runs one test method many times with different inputs from @ValueSource, @CsvSource or @MethodSource - AssertJ fluent assertions
AssertJ makes test assertions read like sentences: assertThat(orders).hasSize(2).extracting(Order::id).containsExactly(1, 2) - Mockito: matchers, verification, spies
Beyond when(...).thenReturn(...): argument matchers (any(), eq()), verification modes (times(2), never()), inOrder, captured arguments, spies (real objects with some methods replaced) and doReturn().when(spy) - JUnit 4 and Hamcrest
JUnit 4 is the older test framework still found in many projects: @Before/@After, @RunWith, @Rule, @Test(expected = ...) and org.junit.Assert
Concurrency beyond the basics
Futures, interruption, synchronizers, queues, thread locals, virtual threads, fork/join, timers, the memory model and deadlocks.
0 of 10 learned
- Runnable, Callable and Future
A Runnable is a task that returns nothing; a Callable<V> returns a value and may throw - Interruption and InterruptedException
interrupt() is a polite request: "please stop what you are doing" - Latches, barriers and semaphores
These classes coordinate threads: CountDownLatch waits until N things have happened, CyclicBarrier makes threads wait for each other, Semaphore limits how many threads may enter at once - Producer-consumer with blocking queues
One group of threads produces work, another consumes it, and a BlockingQueue sits between them: put waits when the queue is full, take waits when it is empty - ThreadLocal and scoped values
A ThreadLocal<T> gives every thread its own private copy of a variable - Virtual threads
A virtual thread is a very cheap thread managed by the JVM instead of the operating system - Fork/Join and divide and conquer
Fork/Join splits a big job into smaller pieces recursively, runs the pieces on a pool of threads, and joins the results - Timers and scheduled executors
ScheduledExecutorService runs a task after a delay or repeatedly - Visibility and the Java Memory Model
Without synchronisation one thread may never see another thread's writes, or may see them in a surprising order - Race conditions and deadlocks
A race condition is a bug where the result depends on the timing of threads (two threads both do "check, then act")
The JVM and the environment
Memory, garbage collection, leaks, class loading, benchmarking, native code and the process around your program.
0 of 11 learned
- The main method, arguments and console input
public static void main(String[] args) is where a Java program starts - System, Runtime and environment
System gives access to the clock, environment variables, system properties and standard streams - Processes and shutdown hooks
ProcessBuilder starts another program from Java and lets you read its output; Runtime.addShutdownHook registers code that runs when the JVM shuts down - ServiceLoader and plug-ins
ServiceLoader.load(Plugin.class) finds every implementation of an interface that is registered on the class path, without the calling code naming any of them - JVM memory: heap, stack and limits
Objects live on the heap, shared by all threads and cleaned by the garbage collector - Garbage collection
The garbage collector frees objects that nothing can reach any more, so Java code never frees memory by hand - Weak and soft references
A normal reference keeps an object alive - Memory leaks in Java
Java has a garbage collector, yet leaks happen: objects that are still reachable but never used again - Class loading and the class path
A class loader finds the bytes of a class (from a jar or folder) and turns them into a Class object the first time the class is needed - Measuring performance and JMH
Timing code with a start and end clock is easy and often wrong: the JIT compiler needs time to warm up and may delete work whose result is unused - Method handles, VarHandle and native code
Method handles are fast, type-checked function pointers that the JIT can inline; VarHandle gives atomic and ordered access to fields; native methods and the Foreign Function & Memory API call code written in C
Design patterns and SOLID
Singleton, builder, factory, strategy, observer, decorator, visitor, template method, DAO and the SOLID principles.
0 of 10 learned
- Singleton pattern
A singleton guarantees one shared instance of a class: a private constructor plus a static accessor - Builder pattern
A builder creates a complex object step by step with readable, named steps (Pizza.builder().size(12).cheese(true).build()), instead of one constructor with many positional parameters - Factory pattern
A factory creates objects for you, hiding which concrete class is chosen: PaymentFactory.create("card") returns a CardPayment behind a Payment interface - Strategy pattern
The strategy pattern puts interchangeable behaviours behind one interface and lets the caller pick one: a PricingStrategy for regular customers and another for members - Observer and event listeners
In the observer pattern an object (the subject) keeps a list of listeners and tells all of them when something happens - Decorator and wrapper classes
A decorator wraps an object of the same interface and adds behaviour before or after delegating: new BufferedReader(new FileReader(f)) adds buffering to a plain reader - Visitor pattern
The visitor pattern lets you add new operations to a family of classes without changing them: each element has an accept(visitor) method that calls back visitor.visit(this), and the visitor decides what to do for each type - Template method pattern
A base class defines the fixed skeleton of an algorithm in a final method and leaves some steps as abstract or overridable hooks that subclasses fill in - DAO and repository pattern
A DAO (data access object) or repository hides how data is stored behind a small interface such as OrderRepository.findById(id) - SOLID principles
SOLID is five guidelines for classes that are easy to change: single responsibility, open/closed, Liskov substitution, interface segregation and dependency inversion
Algorithms and data structures
Recursion, Big O, searching, sorting, dynamic programming, lists, trees, graphs and backtracking in Java.
0 of 11 learned
- Time complexity (Big O)
Big O describes how the running time grows with the input size n - Recursion
A recursive method calls itself on a smaller version of the problem until it reaches a base case it can answer directly - Binary search
Binary search finds a value in a sorted array by repeatedly comparing with the middle element and discarding the half that cannot contain it - Sorting algorithms
Sorting puts items in order - Two pointers and sliding window
Two indexes moving through an array or string replace a nested loop: one from each end (sorted pair sums, palindromes) or one behind the other (a window of elements that grows and shrinks) - Dynamic programming and memoisation
Dynamic programming solves a problem by storing the answers to overlapping smaller problems so each is computed only once - Linked lists
A linked list is a chain of nodes, each holding a value and a reference to the next node - Building your own stack or queue
Writing your own stack or queue (push, pop, enqueue, dequeue) on an array or linked nodes is a standard exercise that shows how the library classes work: an array plus an index, or nodes plus head and tail references - Trees and tree traversal
A tree is a hierarchy of nodes where each node has children (a binary tree has at most a left and a right child) - Graphs: BFS and DFS
A graph is nodes connected by edges (cities and roads, users and friendships) - Backtracking
Backtracking builds a solution step by step, tries each choice, and undoes it (backtracks) when it leads to a dead end
JDBC and everyday libraries
Connections, transactions and result sets, plus Guava, Commons, MapStruct and JavaBeans.
0 of 7 learned
- JDBC connections, DataSource and pools
A Connection is an expensive, stateful channel to the database - JDBC transactions and batching
By default each JDBC statement commits on its own - ResultSet and mapping rows to objects
A ResultSet is a cursor over the rows a query returned: while (rs.next()) moves to the next row and rs.getString("name") reads a column - Guava utilities
Guava is Google's utility library: immutable collections (ImmutableList.of), richer collections (Multimap, BiMap, Table), string helpers (Joiner, Splitter), Preconditions and a simple in-memory cache - Apache Commons helpers
Apache Commons (Lang, Collections, IO, CSV, Codec) offers small null-safe helpers: StringUtils.isBlank(s), CollectionUtils.isEmpty(list), FileUtils.readFileToString, IOUtils.copy, EqualsBuilder, and a CSV parser - MapStruct and object mapping
Object mapping copies data between similar classes, typically entity to DTO - JavaBeans, POJOs and BeanUtils
A JavaBean (or POJO) is a plain class with a no-argument constructor, private fields and public getX/setX methods