Data structures and algorithms, in Java, with working code. Not a reference — a track you can read front to back and come out able to explain and implement each one.
What this covers
Twenty-five posts in reading order. Each stands alone once you have the first five.
- Foundations — what a data structure is, memory, Big O, Omega and Theta.
- Linear structures — arrays, ArrayList, linked lists, stacks, queues, hash tables.
- Techniques — recursion, divide and conquer, dynamic programming, greedy algorithms.
- Searching and sorting — binary search, merge sort, quick sort.
- Trees and heaps — trees, heaps, priority queues, tries.
- Graphs — graphs, BFS, DFS.
Java 25
Everything here is written against Java 25, the LTS released in September 2025.
Nothing depends on a bleeding-edge feature — the algorithms are the same in Java 8 — but records,
enhanced switch and var make the code shorter and the intent clearer, and
there is no reason to teach the 2014 spelling of anything.
Check what you have:
java -version
# openjdk version "25" 2025-09-16 LTSRunning the code
Every implementation in this track is a real file with assertions behind it. There is no build tool, no Maven, no Gradle and no test framework — deliberately, so that you can run any of it with a bare JDK:
javac -d out src/dsa/*.java
java -cp out dsa.RunAlldata structures and algorithms - Java 25
DynamicArray
SinglyLinkedList
ArrayStack
ArrayQueue
HashTable
Searching
Sorting
BinarySearchTree
MinHeap
Trie
Graph
Recursion
DivideAndConquer
DynamicProgramming
Greedy
JdkCollections
261 passed, 0 failedThat matters more than it looks. Published algorithm code is wrong surprisingly often — a
binary search that loops forever on two elements, a queue that reorders itself after it grows —
and those bugs survive because nobody runs the snippet. Everything you are about to read is
compiled with -Werror and asserted against, including the awkward cases: empty input,
one element, duplicates, already-sorted input, and 100,000 elements.
The habit that actually matters
Reading about a data structure and being able to use one are separated by a single practice: implement it once from an empty file, then run it against the ugly inputs.
Not the happy path — an empty collection, a single element, all-equal elements, already-sorted
input, and something big enough that O(n²) hurts. Every non-obvious bug in this track lives in one
of those five, and none of them shows up when you test with {5, 3, 8, 1}.
Two examples you will meet later. The classic queue implementation is correct until the buffer
wraps around and then grows, at which point it silently reorders your data. And
(low + high) / 2 in a binary search overflows on a large array — that bug was in the
JDK's own Arrays.binarySearch for nine years. Both are found by one adversarial test
and by no amount of re-reading.
What this track is not
It is not interview problem practice. For that, the Fundamental Problems track works through LeetCode problems one at a time. This track is the layer underneath: the structures those solutions are built out of, and the reasoning that tells you which one to reach for.
Start with what a data structure actually is.