Medium👤 3-5 years👤 8-15 years 3 min read

ConcurrentHashMap size() vs mappingCount() — Interview Questions

Asked inAmazonGoogleOracle
#concurrenthashmap#size#mappingcount#concurrency#weakly consistent
Report issue

⚡ Short Answer

Both size() and mappingCount() derive from the same underlying mechanism — striped counters summed on demand, with no global lock — so both reflect the map at a moment in time rather than a true snapshot under concurrent modification. The difference is in the contract: size() implements the legacy Map interface, returns int, and caps at Integer.MAX_VALUE for maps that exceed it; mappingCount() returns long and its Javadoc explicitly states 'the value returned is an estimate; the actual count may differ if there are concurrent insertions or removals' — making it both the correct choice for very large maps and the one method where 'this number can be stale' is a documented guarantee, not just an implementation detail you have to infer.

Coffee Chat Question

Concept Made Simple

ConcurrentHashMap.size() vs mappingCount() — why does the Javadoc specifically call one of them 'an estimate'?

🧠Mind Map Answer

Remember It Faster

ConcurrentHashMap never takes a global lock to count entries — doing so would defeat the point of a concurrent map. Instead it maintains striped counters and sums them on demand, the same technique LongAdder uses internally. Both size() and mappingCount() read that sum; they differ in type and documented contract, not in how the number is computed.

size()Map interface method — returns int, caps at Integer.MAX_VALUE
mappingCount()CHM-specific — returns long, Javadoc says 'estimate'
Under concurrent writesNeither is a consistent snapshot — both can be stale
Recommended for large mapsmappingCount() — avoids the int overflow entirely

Key takeaway: the 'estimate' language is mappingCount()'s explicit Javadoc contract — but treat size() with the same caution under concurrent modification, since it's built the same way; it just doesn't say so in its own doc text because it's constrained by the inherited Map contract.

⌨️Hands-on Keyboard

Learn by Doing

java
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

int n = map.size();          // int; capped at Integer.MAX_VALUE; may be stale under concurrent writes
long n2 = map.mappingCount(); // long; Javadoc-documented estimate; correct choice for maps that may exceed Integer.MAX_VALUE

// Neither call locks the map — both read striped counters, summed on demand
// isEmpty() has a stronger, cheaper guarantee: it just checks whether any counter is non-zero

🔥What If?

Think Beyond the Expected

If you need an exact count for a correctness check (not just monitoring), what should you actually do?

Recognize that no method on a live, concurrently-modified ConcurrentHashMap can give you a truly exact count — 'exact' requires either external synchronization that stops writers, or redesigning the check so it doesn't depend on a precise count at all (e.g. using computeIfAbsent for existence checks instead of size()-based logic).

😂Real World

This distinction matters in monitoring/metrics code (size() as a gauge is fine — it's an approximation, and that's an acceptable trade-off for a dashboard) versus correctness-critical logic that mistakenly branches on map.size() == 0 as if it were atomic with a previous write — under concurrency that comparison can be stale the instant it's read, which is a subtly different bug from the classic get-then-put race.

🗣️Real Talk from Guru

I'd point out that both methods are approximations under load — I wouldn't want an interviewer to think I believe size() is exact just because mappingCount() is the one with 'estimate' in its Javadoc. The real lesson is: don't use size() for correctness decisions on a concurrent map, only for observability.

🎯Interviewer's Expectation

Keywords they're listening for:

Knows both use the same striped-counter mechanism, no global lockCorrectly attributes the 'estimate' Javadoc language to mappingCount()Knows size() is int-capped, mappingCount() is longDoesn't treat either as a consistent snapshot under concurrent writes

⚠️Common Mistakes

  • Assuming size() is exact on a concurrently-modified map
  • Branching correctness-critical logic on a stale size()/mappingCount() read
  • Not knowing mappingCount() exists as the long-returning, large-map-safe alternative

Best Practices

  • Use mappingCount() over size() when the map may be very large
  • Treat both as observability signals, not correctness guarantees, under concurrent writes
  • Use isEmpty() or atomic compound methods (computeIfAbsent/merge) for correctness checks instead

🔁Follow-up Questions

  • 1Why doesn't ConcurrentHashMap just lock the whole map to compute an exact size?
  • 2What guarantee does isEmpty() give that size() doesn't?
  • 3How would LongAdder relate to how these counts are maintained internally?

🧩Related Technologies

LongAdderAtomicLongMap

Continue Learning with AI

Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.

Plain-language foundations

I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner.

Topic: ConcurrentHashMap (Java Collections)
Interview question: "ConcurrentHashMap.size() vs mappingCount() — why does the Javadoc specifically call one of them 'an estimate'?"

Please:
1. Explain the core idea in simple, plain language, using an everyday analogy.
2. Define any technical terms you use.
3. Walk through one small, concrete example.
4. Finish with a single sentence I can easily remember.

Keep the tone friendly and assume I'm new to this topic.
Open inChatGPTGeminiClaude

Was this answer helpful?

Support our platform by exploring our recommended products.

As an Amazon affiliate, purchases through these links may earn us a small commission — at no extra cost to you. It helps keep Full Stack Interview Guru free.

Related Questions