Pick a hash function, press Play, and watch objects fill the buckets.
An interactive simulator for Java's HashMap internals — hashing, the
h ^ (h >>> 16) spread, (n-1) & hash indexing, collisions, resizing, and the
moment a bucket's linked list becomes a red-black tree.
Built with Next.js · TypeScript · Tailwind CSS · Framer Motion · Zustand
Most explanations of hashCode() are static diagrams and long paragraphs. HashLab is the
opposite: press Play and objects are hashed and dropped into HashMap buckets one by one, so you
watch a good hash spread evenly and a bad one collapse everything into a single bucket.
| Page | What it does |
|---|---|
| Playground | Pick a hashCode(), press Play, and objects auto-insert into buckets. Shows the hashing pipeline, live bucket distribution, a red-black tree view when a bucket treeifies, live metrics, and a merged Performance at scale panel (good/poor/worst at 10 → 5,000 objects). One-click presets: Even spread, Collisions, Treeify → RB tree. |
| Interview | The questions every Java interview asks, with expandable answers, the hashCode/equals contract truth-table and five golden rules. |
Two completely independent layers:
React UI → useSimulator hook → CollectionEngine → Hash strategies → Event stream → Visualization
Every operation returns an ordered stream of typed events
(HASH_CALCULATED → HASH_SPREAD → BUCKET_SELECTED → COLLISION_FOUND → OBJECT_INSERTED) plus an
immutable snapshot. The engine knows nothing about the DOM.
simulation/
├── types.ts # Event / Bucket / Statistics shapes
├── hashing/
│ ├── javaHash.ts # 32-bit-faithful String/Objects hash, spread, index
│ └── strategies.ts # Strategy pattern: return 1, id, age, Objects.hash, 31·h, UUID, Random…
├── objects/objects.ts # Person keys + Java-style equals()
└── engine/
├── CollectionEngine.ts # HashMap core: put, resize, treeify + fast bulkPut
└── MetricsEngine.ts # Live statistics from bucket state
The UI is a pure function of the current frame. Framer Motion's layout animations move object
chips between buckets during a resize automatically, and the red-black tree is drawn from the
treeified bucket's entries.
- 32-bit integer math via
Math.imul+| 0, soString.hashCode()andObjects.hash()match a real JVM. - Spread:
h ^ (h >>> 16). Index:(n - 1) & hash(fast modulo on a power-of-two table). equals()only runs when stored hashes match — so a good hash also cutsequals()calls (the Performance panel shows 0 equals for a good hash vs. n(n-1)/2 forreturn 1).- Resize at
size > capacity × loadFactor; treeify at chain length 8 with capacity ≥ 64.
Blue = hashing · Green = correct · Yellow = collision · Orange = resize · Purple = treeification · Red = broken contract.
npm install
npm run dev # http://localhost:3000
npm run build # production buildZero-config on Vercel — import the repo and deploy. No environment variables, no backend; everything is simulated in the browser.