It all depends. I was thinking mainly of small keys that are at most a machine word. But yes I conceded that for large keys (extremely unusual for what I do, thus I didn't think of that case before) a hashmap wins.
Also, while on a desktop class CPU any pointer chasing you do tends to dominate, that is not the case on small and medium microcontrollers (which I work with a lot). They have very short pipelines and their memory is all internal SRAM most of the time. Here classic cycle counting is still king, so you need to ask yourself if it is quicker to compare the key than to calculate the hash and compare hashes.
Code size in general matters a lot on embedded. Even a simple hashmap will always have more code than a simple vector. And a state of the art implementation with probing and tombstones (such as swisstable in C++ and hashbrown in Rust) will be way too large to be usable.
Also, while on a desktop class CPU any pointer chasing you do tends to dominate, that is not the case on small and medium microcontrollers (which I work with a lot). They have very short pipelines and their memory is all internal SRAM most of the time. Here classic cycle counting is still king, so you need to ask yourself if it is quicker to compare the key than to calculate the hash and compare hashes.
Code size in general matters a lot on embedded. Even a simple hashmap will always have more code than a simple vector. And a state of the art implementation with probing and tombstones (such as swisstable in C++ and hashbrown in Rust) will be way too large to be usable.