October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

Fail-Fast HashMap: Why a Modification Counter Beats a Boolean Flag

A shared Boolean cannot reliably track what each live iterator observed. A modification counter and per-iterator snapshot provide a clearer best-effort check for structural changes.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A fail-fast iterator needs to know whether the map’s structure has changed since that particular iterator began. A single shared Boolean cannot reliably record that relationship across successive changes and multiple live iterators. The usual design is a map-level modification counter, such as modCount, paired with an iterator-local snapshot, such as expectedModCount. This detects some invalidating changes; it does not make the map thread-safe or guarantee that every race will be reported.

What fail-fast iteration is meant to catch

Suppose an iterator is walking a map while code elsewhere adds or removes a mapping. The iterator’s view of the map’s structure may no longer match the structure it expects to traverse. A fail-fast iterator checks for that kind of unexpected change and may throw Java’s ConcurrentModificationException.

As an Amazon Associate I earn from qualifying purchases.

Despite its name, the exception does not require multiple threads. A single thread can trigger it by structurally modifying the map through another reference or code path while an iterator is active.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For Java’s HashMap, Oracle defines a structural modification as adding or deleting one or more mappings. Replacing the value associated with a key that is already present is not structural. The API says collection-view iterators throw ConcurrentModificationException when the map is structurally modified after iterator creation, except through the iterator’s own remove() method. Oracle Java SE 26 HashMap API

Why one Boolean loses useful information

A Boolean can say that a change happened, but it cannot describe which version of the map an iterator observed. If the flag stays set forever, it cannot distinguish a new change from the one an iterator already detected. If code clears it after one iterator checks, another live iterator may miss the change. A shared flag also gives separate iterators no independent record of their starting state.

A counter and a per-iterator snapshot encode the comparison directly: the map tracks its current structural version, and each iterator remembers the version it saw at construction. OpenJDK’s HashMap uses the fields modCount and expectedModCount for this pattern. OpenJDK HashMap source

Design What it remembers Successive changes Multiple live iterators Iterator-owned removal
One shared Boolean Only whether a change flag is currently set; it does not preserve each iterator’s observed state. Cannot distinguish a later change from an earlier one while the flag remains set. Clearing the flag for one iterator can hide a change from another. Cannot naturally resynchronize only the iterator that performed the removal.
Map counter plus iterator snapshot The map’s current modification count and the count observed by each iterator. A changed count differs from an earlier snapshot, unless a finite-width counter eventually wraps around. Each iterator keeps its own snapshot and can compare it independently. The iterator can refresh its own snapshot after its authorized removal.

How the counter-and-snapshot pattern works

For a custom map, define which operations invalidate traversal, increment the map’s count when those structural changes succeed, and capture the count separately for every iterator. Before an iterator consumes or advances into structure, it compares its saved count with the map’s current count.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
map.structuralChange():
    map.modCount += 1

iterator created:
    iterator.expectedModCount = map.modCount

iterator.next():
    if iterator.expectedModCount != map.modCount:
        throw ConcurrentModificationException
    return nextEntry

iterator.remove():
    removeCurrentEntry()
    iterator.expectedModCount = map.modCount

This is conceptual pseudocode, not a claim about a particular custom implementation. It captures the essential relationship: one shared version number on the map, one observed version per iterator.

Choose and count structural changes consistently

The counter is useful only if its update rules match the iterator’s invalidation rules. For Java HashMap semantics, successful insertion of a new key and successful removal of a mapping are structural changes; replacing the value of an existing key is not. If a custom map reorganizes its internal structure—for example, by resizing—and that makes an active traversal unsafe, its contract should treat that operation as invalidating traversal and account for it.

OpenJDK’s implementation notes that structural changes can include changes to internal structure, such as rehashing. A custom implementation should state its own rule clearly rather than assume every internal update has the same effect. OpenJDK HashMap source

Check the iterator operations that consume structure

In OpenJDK’s HashMap, the modification-count comparison occurs in HashIterator.nextNode(), which is used when obtaining the next node. Do not assume that every iterator method performs the check: for example, hasNext() only tests whether a next node exists in that implementation. If your map offers split or bulk traversal, such as a spliterator, review those traversal paths separately and apply a consistent policy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make iterator removal a controlled exception

An iterator’s own remove() is allowed because the iterator can update its snapshot after its removal succeeds. That way, its authorized structural change does not immediately look like an outside modification. In OpenJDK, the iterator refreshes expectedModCount after removing the current node.

The iterator must also enforce the normal removal state rules: removal before a successful next(), or a second removal without another next(), is invalid. Checking only the modification count is not enough to implement the Iterator contract.

Fail-fast checks are not a concurrency guarantee

Oracle explicitly warns that fail-fast behavior is best effort: it is generally impossible to guarantee detection in the presence of unsynchronized concurrent modification. The API also says programs must not depend on ConcurrentModificationException for correctness; the exception is intended to help detect bugs. Oracle Java SE 26 HashMap API

A modification counter is not a lock, does not provide memory visibility, and does not make concurrent access safe. If threads share a map and may structurally modify it, use external synchronization or choose a collection designed for concurrent access. The counter’s job is narrower: detect some unexpected structural changes during traversal.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.