From charlesreid1

(Add Python mapping protocol section alongside the existing Java Map interface section (via update-page on MediaWiki MCP Server))
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Map Abstract Data Type==
The '''Map Abstract Data Type''' (ADT) defines the interface contract that all [[Maps|map]] implementations must satisfy. It specifies ''what'' operations a map supports without prescribing ''how'' they are implemented — the hallmark of an ADT. A concrete map implementation may use a hash table, a balanced tree, a sorted array, or any other suitable data structure.


The map abstract data type must support the following basic operations:
A map stores key-value pairs. Each key maps to exactly one value (the map is a [[Wikipedia:Function (mathematics)|function]] from a domain of keys to a codomain of values). Keys must be unique; distinct keys may map to the same value.
* m[k] or m.get(k) - get the value v associated with key k in map m, returns key error
* m[k] = v or m.set(k,v) or m.put(k,v) - set the value v associated with key k in map m
* del m[k] or m.remove(k) - remove the element with key k in map m
* len(m) or m.size() - return the number of elements (unique keys) in the map
* iter(m) - iterator over keys of map


Other convenience methods:
==Basic operations==
* m.contains(k) or k in m - perform search to see if map m contains key k
* m.get(k, d=None) - return m[k] if key k exists in the map, otherwise return a default value in place of a key error
* m.setdefault(k,d) - if key k exists in map, return m[k]. otherwise, set m[k] to default value d and return value
* m.pop(k, d=None) - remove item associated with key k from map and return associated value v
* m.popItem() - remove arbitrary key-vlue pair from the map, and return a (k,v) tuple representing the removed pair. raise key error if empty map.
* m.clear() - remove key-value pairs from map
* m.keys() - return set-like view of keys
* m.value() - return set-like view of values
* m.items() - return set-like view of (k,v) tuples for entries of m
* m.update(m2) - assign m[k] = v for every (k,v) pair in map m2
* m.equals(m2) m.compareTo(m2) etc.


==Flags==
These five operations constitute the essential interface of any map ADT:
 
{| class="wikitable"
|-
! Operation !! Pseudocode signatures !! Description
|-
| '''get''' || <code>m[k]</code>, <code>m.get(k)</code>
| Return the value associated with key <code>k</code>; raise a ''key error'' if <code>k</code> is absent.
|-
| '''set''' || <code>m[k] = v</code>, <code>m.put(k, v)</code>
| Associate value <code>v</code> with key <code>k</code>, overwriting any previous mapping.
|-
| '''remove''' || <code>del m[k]</code>, <code>m.remove(k)</code>
| Remove the entry for key <code>k</code>; raise a key error if absent.
|-
| '''size''' || <code>len(m)</code>, <code>m.size()</code>
| Return the number of key-value pairs in the map.
|-
| '''iterate''' || <code>iter(m)</code>
| Return an iterator over the keys of the map.
|}
 
==Convenience operations==
 
These operations can each be expressed in terms of the basic five above, but are provided for programmer convenience.
 
===Lookup===
 
* <code>m.contains(k)</code> / <code>k '''in''' m</code> — test whether key <code>k</code> exists in the map; returns boolean
* <code>m.get(k, d)</code> — return <code>m[k]</code> if key <code>k</code> exists; otherwise return default value <code>d</code>
* <code>m.setdefault(k, d)</code> — if key <code>k</code> exists return <code>m[k]</code>; otherwise set <code>m[k] = d</code> and return <code>d</code>
 
===Modification===
 
* <code>m.pop(k, d)</code> — remove key <code>k</code> and return its associated value; return <code>d</code> if key is absent
* <code>m.popitem()</code> — remove and return an arbitrary <code>(k, v)</code> pair; raise a key error if the map is empty
* <code>m.clear()</code> — remove all key-value pairs from the map
 
===Views===
 
* <code>m.keys()</code> — return a set-like view of all keys
* <code>m.values()</code> — return a set-like view of all values
* <code>m.items()</code> — return a set-like view of all <code>(k, v)</code> tuples
 
Views are live: changes to the underlying map are reflected in the view, and vice versa.
 
===Bulk operations===
 
* <code>m.update(m2)</code> — for every <code>(k, v)</code> pair in map <code>m2</code>, set <code>m[k] = v</code>
* <code>m.equals(m2)</code> — return true if the two maps contain the same key-value pairs
 
==Expected complexity==
 
While the ADT itself is implementation-agnostic, useful map implementations achieve the following amortized bounds:
 
{| class="wikitable"
|-
! Implementation !! <code>get</code> !! <code>put</code> !! <code>remove</code> !! <code>contains</code>
|-
| Hash table || O(1) || O(1) || O(1) || O(1)
|-
| Balanced BST || O(log n) || O(log n) || O(log n) || O(log n)
|-
| Unsorted array || O(n) || O(n) || O(n) || O(n)
|-
| Sorted array || O(log n) || O(n) || O(n) || O(log n)
|}
 
==Java Map interface==
 
The Java Collections Framework specifies the map ADT through the <code>[http://docs.oracle.com/javase/8/docs/api/java/util/Map.html java.util.Map&lt;K,V&gt;]</code> interface.
 
===Core methods===
 
{| class="wikitable"
|-
! Method !! Description
|-
| <code>size()</code> || Return the number of key-value mappings.
|-
| <code>isEmpty()</code> || Return <code>true</code> if the map contains no mappings.
|-
| <code>get(Object key)</code> || Return the value to which <code>key</code> is mapped, or <code>null</code> if absent.
|-
| <code>put(K key, V value)</code> || Associate <code>value</code> with <code>key</code>; return the previous value, or <code>null</code>.
|-
| <code>remove(Object key)</code> || Remove the mapping for <code>key</code>; return the previous value, or <code>null</code>.
|-
| <code>containsKey(Object key)</code> || Return <code>true</code> if the map contains <code>key</code>.
|-
| <code>containsValue(Object value)</code> || Return <code>true</code> if the map maps one or more keys to <code>value</code>.
|-
| <code>keySet()</code> || Return a <code>Set&lt;K&gt;</code> view of the keys.
|-
| <code>values()</code> || Return a <code>Collection&lt;V&gt;</code> view of the values.
|-
| <code>entrySet()</code> || Return a <code>Set&lt;Map.Entry&lt;K,V&gt;&gt;</code> view of the entries.
|}
 
===Bulk and default methods===
 
{| class="wikitable"
|-
! Method !! Description
|-
| <code>putAll(Map m)</code> || Copy all mappings from <code>m</code> into this map.
|-
| <code>clear()</code> || Remove all mappings.
|-
| <code>getOrDefault(Object key, V def)</code> || Return value for <code>key</code>, or <code>def</code> if absent. (Java 8)
|-
| <code>putIfAbsent(K key, V value)</code> || Insert only if <code>key</code> is not already present. (Java 8)
|-
| <code>replace(K key, V old, V new)</code> || Replace value only if currently mapped to <code>old</code>. (Java 8)
|-
| <code>computeIfAbsent(K key, Function f)</code> || If <code>key</code> is absent, compute and insert a value via <code>f</code>. (Java 8)
|-
| <code>merge(K key, V val, BiFunction remap)</code> || Merge <code>val</code> with existing value using <code>remap</code>. (Java 8)
|}
 
Standard implementations: <code>HashMap</code> (hash table, O(1) expected), <code>TreeMap</code> (red-black tree, O(log n)), <code>LinkedHashMap</code> (hash table with insertion-order iteration).
 
==Python mapping protocol==
 
Python specifies the map ADT through two abstract base classes in <code>[https://docs.python.org/3/library/collections.abc.html collections.abc]</code>: the read-only <code>Mapping</code> and the mutable <code>MutableMapping</code> (which extends <code>Mapping</code>). The built-in <code>dict</code> type is the primary concrete implementation; user-defined map types can register as virtual subclasses or inherit directly from these ABCs.
 
The ABC hierarchy relevant to maps:
 
* <code>Container</code> → <code>Collection</code> → <code>Mapping</code> → <code>MutableMapping</code>
* <code>Iterable</code> → <code>Collection</code>
* <code>Sized</code> → <code>Collection</code>
 
A minimal concrete <code>MutableMapping</code> must implement five abstract methods: <code>__getitem__</code>, <code>__setitem__</code>, <code>__delitem__</code>, <code>__iter__</code>, and <code>__len__</code>. All other mixin methods are derived from these five.
 
===Core methods — <code>Mapping</code> (read-only)===
 
{| class="wikitable"
|-
! Method !! Description
|-
| <code>m[k]</code> (<code>__getitem__</code>) || Return the value for key <code>k</code>; raise <code>KeyError</code> if absent. ''Abstract.''
|-
| <code>k '''in''' m</code> (<code>__contains__</code>) || Return <code>True</code> if key <code>k</code> is present. Default: iterate and compare.
|-
| <code>len(m)</code> (<code>__len__</code>) || Return the number of key-value pairs. ''Abstract.''
|-
| <code>iter(m)</code> (<code>__iter__</code>) || Return an iterator over the keys. ''Abstract.''
|-
| <code>m.keys()</code> || Return a <code>KeysView</code> (set-like) of all keys.
|-
| <code>m.values()</code> || Return a <code>ValuesView</code> of all values.
|-
| <code>m.items()</code> || Return an <code>ItemsView</code> (set-like) of <code>(k, v)</code> tuples.
|-
| <code>m.get(k, d=None)</code> || Return <code>m[k]</code> if key exists; otherwise return default <code>d</code>.
|-
| <code>m == m2</code> (<code>__eq__</code>) || Return <code>True</code> if both maps have the same key-value pairs.
|}
 
All views are live: they reflect changes to the underlying map.
 
===Mutable methods — <code>MutableMapping</code>===
 
{| class="wikitable"
|-
! Method !! Description
|-
| <code>m[k] = v</code> (<code>__setitem__</code>) || Insert or overwrite the mapping for key <code>k</code>. ''Abstract.''
|-
| <code>del m[k]</code> (<code>__delitem__</code>) || Remove the mapping for key <code>k</code>; raise <code>KeyError</code> if absent. ''Abstract.''
|-
| <code>m.pop(k, d)</code> || Remove key <code>k</code> and return its value; return <code>d</code> (or raise <code>KeyError</code>) if absent.
|-
| <code>m.popitem()</code> || Remove and return an arbitrary <code>(k, v)</code> pair; raise <code>KeyError</code> if empty.
|-
| <code>m.setdefault(k, d=None)</code> || Return <code>m[k]</code> if present; otherwise set <code>m[k] = d</code> and return <code>d</code>.
|-
| <code>m.clear()</code> || Remove all key-value pairs.
|-
| <code>m.update(m2)</code> || For every <code>(k, v)</code> in <code>m2</code> (or from keyword arguments), set <code>m[k] = v</code>.
|}
 
===Dict-specific methods===
 
Beyond the <code>MutableMapping</code> contract, <code>dict</code> provides:
 
{| class="wikitable"
|-
! Method !! Description
|-
| <code>dict.fromkeys(iterable, v=None)</code> || Class method: build a new dict with keys from an iterable, all mapped to value <code>v</code>.
|-
| <code>m.copy()</code> || Return a shallow copy of the dict.
|-
| <code>m {{!}} m2</code> (<code>__or__</code>) || Return a new dict merging <code>m</code> and <code>m2</code>. (Python 3.9+)
|-
| <code>m {{!}}= m2</code> (<code>__ior__</code>) || In-place merge: update <code>m</code> with <code>m2</code>. (Python 3.9+)
|-
| <code>reversed(m)</code> (<code>__reversed__</code>) || Return a reverse iterator over keys. (Python 3.8+)
|}
 
===Standard implementations===
 
{| class="wikitable"
|-
! Class !! Module !! Backing !! Notes
|-
| <code>dict</code> || built-in || Hash table, O(1) expected || The default mapping type. Insertion-ordered since Python 3.7.
|-
| <code>OrderedDict</code> || <code>collections</code> || Doubly-linked list + hash table || Remembers insertion order (present since Python 3.1; <code>dict</code> also preserves order since 3.7, but <code>OrderedDict</code> adds <code>move_to_end</code> and order-sensitive equality).
|-
| <code>defaultdict</code> || <code>collections</code> || Hash table || Missing keys are auto-created by a user-supplied factory function.
|-
| <code>Counter</code> || <code>collections</code> || Hash table || Multiset: keys map to integer counts. Supports <code>+</code>, <code>-</code>, <code>&amp;</code>, <code>|</code> operators.
|-
| <code>ChainMap</code> || <code>collections</code> || Linked list of mappings || Chains multiple mappings together; lookups search each in order.
|-
| <code>MappingProxyType</code> || <code>types</code> || Wraps a dict || Read-only dynamic view onto another mapping.
|}
 
Python has no balanced-BST map in the standard library. Third-party packages such as [https://grantjenks.com/docs/sortedcontainers/ sortedcontainers] provide <code>SortedDict</code> with O(log n) operations.
 
===Example: minimal custom <code>MutableMapping</code>===
 
<syntaxhighlight lang="python">
from collections.abc import MutableMapping
 
class SingleEntryMap(MutableMapping):
    """A map that holds at most one key-value pair."""
 
    def __init__(self):
        self._key = None
        self._value = None
 
    def __getitem__(self, key):
        if self._key == key:
            return self._value
        raise KeyError(key)
 
    def __setitem__(self, key, value):
        self._key = key
        self._value = value
 
    def __delitem__(self, key):
        if self._key == key:
            self._key = None
            self._value = None
        else:
            raise KeyError(key)
 
    def __iter__(self):
        if self._key is not None:
            yield self._key
 
    def __len__(self):
        return 1 if self._key is not None else 0
 
    def __repr__(self):
        return repr(dict(self)) if self._key is not None else '{}'
</syntaxhighlight>
 
Implementing the five abstract methods automatically provides <code>keys()</code>, <code>values()</code>, <code>items()</code>, <code>get()</code>, <code>pop()</code>, <code>popitem()</code>, <code>setdefault()</code>, <code>clear()</code>, <code>update()</code>, <code>__contains__</code>, and <code>__eq__</code> — all supplied by the <code>MutableMapping</code> mixin.
 
==See also==
 
* [[Maps]] — main Maps page with implementation notes
* [[Maps/AbstractMap]] — abstract base class
* [[Maps/UnsortedArrayMap]] — array-based concrete implementation
* [[Maps/SortedArrayMap]] — sorted-array concrete implementation
* [[Hash Maps]] — hash-table implementations (chaining and probing)
* [[Maps/Operations and Performance]] — timing benchmarks


{{MapsFlag}}
{{MapsFlag}}

Latest revision as of 04:12, 8 June 2026

The Map Abstract Data Type (ADT) defines the interface contract that all map implementations must satisfy. It specifies what operations a map supports without prescribing how they are implemented — the hallmark of an ADT. A concrete map implementation may use a hash table, a balanced tree, a sorted array, or any other suitable data structure.

A map stores key-value pairs. Each key maps to exactly one value (the map is a function from a domain of keys to a codomain of values). Keys must be unique; distinct keys may map to the same value.

Basic operations

These five operations constitute the essential interface of any map ADT:

Operation Pseudocode signatures Description
get m[k], m.get(k) Return the value associated with key k; raise a key error if k is absent.
set m[k] = v, m.put(k, v) Associate value v with key k, overwriting any previous mapping.
remove del m[k], m.remove(k) Remove the entry for key k; raise a key error if absent.
size len(m), m.size() Return the number of key-value pairs in the map.
iterate iter(m) Return an iterator over the keys of the map.

Convenience operations

These operations can each be expressed in terms of the basic five above, but are provided for programmer convenience.

Lookup

  • m.contains(k) / k in m — test whether key k exists in the map; returns boolean
  • m.get(k, d) — return m[k] if key k exists; otherwise return default value d
  • m.setdefault(k, d) — if key k exists return m[k]; otherwise set m[k] = d and return d

Modification

  • m.pop(k, d) — remove key k and return its associated value; return d if key is absent
  • m.popitem() — remove and return an arbitrary (k, v) pair; raise a key error if the map is empty
  • m.clear() — remove all key-value pairs from the map

Views

  • m.keys() — return a set-like view of all keys
  • m.values() — return a set-like view of all values
  • m.items() — return a set-like view of all (k, v) tuples

Views are live: changes to the underlying map are reflected in the view, and vice versa.

Bulk operations

  • m.update(m2) — for every (k, v) pair in map m2, set m[k] = v
  • m.equals(m2) — return true if the two maps contain the same key-value pairs

Expected complexity

While the ADT itself is implementation-agnostic, useful map implementations achieve the following amortized bounds:

Implementation get put remove contains
Hash table O(1) O(1) O(1) O(1)
Balanced BST O(log n) O(log n) O(log n) O(log n)
Unsorted array O(n) O(n) O(n) O(n)
Sorted array O(log n) O(n) O(n) O(log n)

Java Map interface

The Java Collections Framework specifies the map ADT through the java.util.Map<K,V> interface.

Core methods

Method Description
size() Return the number of key-value mappings.
isEmpty() Return true if the map contains no mappings.
get(Object key) Return the value to which key is mapped, or null if absent.
put(K key, V value) Associate value with key; return the previous value, or null.
remove(Object key) Remove the mapping for key; return the previous value, or null.
containsKey(Object key) Return true if the map contains key.
containsValue(Object value) Return true if the map maps one or more keys to value.
keySet() Return a Set<K> view of the keys.
values() Return a Collection<V> view of the values.
entrySet() Return a Set<Map.Entry<K,V>> view of the entries.

Bulk and default methods

Method Description
putAll(Map m) Copy all mappings from m into this map.
clear() Remove all mappings.
getOrDefault(Object key, V def) Return value for key, or def if absent. (Java 8)
putIfAbsent(K key, V value) Insert only if key is not already present. (Java 8)
replace(K key, V old, V new) Replace value only if currently mapped to old. (Java 8)
computeIfAbsent(K key, Function f) If key is absent, compute and insert a value via f. (Java 8)
merge(K key, V val, BiFunction remap) Merge val with existing value using remap. (Java 8)

Standard implementations: HashMap (hash table, O(1) expected), TreeMap (red-black tree, O(log n)), LinkedHashMap (hash table with insertion-order iteration).

Python mapping protocol

Python specifies the map ADT through two abstract base classes in collections.abc: the read-only Mapping and the mutable MutableMapping (which extends Mapping). The built-in dict type is the primary concrete implementation; user-defined map types can register as virtual subclasses or inherit directly from these ABCs.

The ABC hierarchy relevant to maps:

  • ContainerCollectionMappingMutableMapping
  • IterableCollection
  • SizedCollection

A minimal concrete MutableMapping must implement five abstract methods: __getitem__, __setitem__, __delitem__, __iter__, and __len__. All other mixin methods are derived from these five.

Core methods — Mapping (read-only)

Method Description
m[k] (__getitem__) Return the value for key k; raise KeyError if absent. Abstract.
k in m (__contains__) Return True if key k is present. Default: iterate and compare.
len(m) (__len__) Return the number of key-value pairs. Abstract.
iter(m) (__iter__) Return an iterator over the keys. Abstract.
m.keys() Return a KeysView (set-like) of all keys.
m.values() Return a ValuesView of all values.
m.items() Return an ItemsView (set-like) of (k, v) tuples.
m.get(k, d=None) Return m[k] if key exists; otherwise return default d.
m == m2 (__eq__) Return True if both maps have the same key-value pairs.

All views are live: they reflect changes to the underlying map.

Mutable methods — MutableMapping

Method Description
m[k] = v (__setitem__) Insert or overwrite the mapping for key k. Abstract.
del m[k] (__delitem__) Remove the mapping for key k; raise KeyError if absent. Abstract.
m.pop(k, d) Remove key k and return its value; return d (or raise KeyError) if absent.
m.popitem() Remove and return an arbitrary (k, v) pair; raise KeyError if empty.
m.setdefault(k, d=None) Return m[k] if present; otherwise set m[k] = d and return d.
m.clear() Remove all key-value pairs.
m.update(m2) For every (k, v) in m2 (or from keyword arguments), set m[k] = v.

Dict-specific methods

Beyond the MutableMapping contract, dict provides:

Method Description
dict.fromkeys(iterable, v=None) Class method: build a new dict with keys from an iterable, all mapped to value v.
m.copy() Return a shallow copy of the dict.
m2 (__or__) Return a new dict merging m and m2. (Python 3.9+)
= m2 (__ior__) In-place merge: update m with m2. (Python 3.9+)
reversed(m) (__reversed__) Return a reverse iterator over keys. (Python 3.8+)

Standard implementations

Class Module Backing Notes
dict built-in Hash table, O(1) expected The default mapping type. Insertion-ordered since Python 3.7.
OrderedDict collections Doubly-linked list + hash table Remembers insertion order (present since Python 3.1; dict also preserves order since 3.7, but OrderedDict adds move_to_end and order-sensitive equality).
defaultdict collections Hash table Missing keys are auto-created by a user-supplied factory function.
Counter collections Hash table operators.
ChainMap collections Linked list of mappings Chains multiple mappings together; lookups search each in order.
MappingProxyType types Wraps a dict Read-only dynamic view onto another mapping.

Python has no balanced-BST map in the standard library. Third-party packages such as sortedcontainers provide SortedDict with O(log n) operations.

Example: minimal custom MutableMapping

from collections.abc import MutableMapping

class SingleEntryMap(MutableMapping):
    """A map that holds at most one key-value pair."""

    def __init__(self):
        self._key = None
        self._value = None

    def __getitem__(self, key):
        if self._key == key:
            return self._value
        raise KeyError(key)

    def __setitem__(self, key, value):
        self._key = key
        self._value = value

    def __delitem__(self, key):
        if self._key == key:
            self._key = None
            self._value = None
        else:
            raise KeyError(key)

    def __iter__(self):
        if self._key is not None:
            yield self._key

    def __len__(self):
        return 1 if self._key is not None else 0

    def __repr__(self):
        return repr(dict(self)) if self._key is not None else '{}'

Implementing the five abstract methods automatically provides keys(), values(), items(), get(), pop(), popitem(), setdefault(), clear(), update(), __contains__, and __eq__ — all supplied by the MutableMapping mixin.

See also