An interchangeable key/value HashMap Set structure
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
An "interchangeable key/value" map is usually a bidirectional map, often called a BiMap. The idea is simple: if A maps to 1, you want to be able to look up 1 and get back A with the same efficiency.
What Problem This Structure Solves
A normal HashMap gives you fast lookup in one direction only. If you also need fast reverse lookup, searching all entries is too slow.
The usual fix is to maintain two hash maps:
- '
forward:key -> value' - '
reverse:value -> key'
That gives average O(1) lookup in both directions. The tradeoff is that every write must keep both maps consistent.
This only works cleanly when the mapping is one-to-one. If two different keys may share the same value, the reverse side is no longer a plain map.
Core Invariant
The data structure is correct only if these statements are always true:
- Every key appears at most once in
forward. - Every value appears at most once in
reverse. - '
forward[k] == vif and only ifreverse[v] == k.'
Once you think in terms of invariants, the implementation becomes straightforward. Insert, update, and remove operations all exist to preserve that relationship.
Java Implementation with Two HashMaps
The following example shows a small generic implementation. It rejects duplicate keys and duplicate values so the mapping remains invertible.
This is the standard design because it keeps both directions explicit and easy to reason about.
Updates Are Harder Than Reads
Reads are trivial. Updates are where bugs usually appear.
Suppose you want to replace alice -> 101 with alice -> 205. You must:
- Remove the old reverse entry for
101. - Verify that
205is not already assigned to someone else. - Write the new pair to both maps.
If you update one side and forget the other, the structure becomes corrupt. That is why mature libraries often wrap bidirectional maps in a dedicated type instead of exposing two independent maps directly.
When You Need Sets Instead of Single Values
If values are not unique, the structure is not really interchangeable anymore. For example, if both alice and bob can belong to "admin", then reverse lookup must return a collection:
- '
Map<K, V>for the forward direction' - '
Map<V, Set<K>>for the reverse direction'
That is still a valid design, but it is no longer a one-to-one BiMap. It is better described as dual indexes or two synchronized maps.
Existing Libraries
Before writing your own version, check whether your language already provides one:
- Java: Guava has
BiMap - Python: third-party packages such as
bidict - C++: Boost has multi-index containers for similar needs
A library implementation usually handles corner cases such as replacement semantics, iteration, and view consistency more carefully than ad hoc code.
Common Pitfalls
The most common mistake is forgetting that bidirectional lookup requires value uniqueness. If multiple keys can share a value, reverse lookup cannot return a single answer.
Another mistake is updating only one map during removal or reassignment. That leaves stale entries behind and causes mismatched lookups later.
People also underestimate concurrency issues. Two maps must be updated atomically if the structure is shared across threads. If you need thread safety, protect both maps with the same lock or use a purpose-built concurrent abstraction.
Finally, do not describe this as a "set" unless the semantics are actually set-like. Most of the time the right term is bidirectional map.
Summary
- An interchangeable key/value structure is usually a bidirectional map, not a special kind of HashSet.
- The standard implementation uses two hash maps: one forward and one reverse.
- The design only works cleanly when keys and values are both unique.
- Writes must update both maps together to preserve the invariant.
- If duplicates are allowed on either side, use maps of sets instead of a one-to-one
BiMap.

