# HashMap with tuple keys

**URL:** <https://users.rust-lang.org/t/hashmap-with-tuple-keys/12711>\
**Category:** help\
**Created:** [September 4, 2017, 3:06pm UTC](https://users.rust-lang.org/t/hashmap-with-tuple-keys/12711 "2017-09-04T15:06:17Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![dtolnay](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/dtolnay/32/2115_2.png) [@dtolnay](https://users.rust-lang.org/u/dtolnay)\
**Post date:** [September 4, 2017, 4:48pm UTC](https://users.rust-lang.org/t/hashmap-with-tuple-keys/12711/2 "2017-09-04T16:48:08Z")

</div>

Here is one possible implementation. [[playground]](https://play.rust-lang.org/?gist=50f5558bd9c9fe3d7740ba6435471faa)

```rust
use std::collections::HashMap;
use std::mem::ManuallyDrop;
use std::ptr;

fn get(map: HashMap<(String, String), i64>, a: &String, b: &String) -> Option<i64> {
    unsafe {
        // The 24-byte string headers of `a` and `b` may not be adjacent in
        // memory. Copy them (just the headers) so that they are adjacent. This
        // makes a `(String, String)` backed by the same data as `a` and `b`.
        let k = (ptr::read(a), ptr::read(b));

        // Make sure not to drop the strings, even if `get` panics. The caller
        // or whoever owns `a` and `b` will drop them.
        let k = ManuallyDrop::new(k);

        // Deref `k` to get `&(String, String)` and perform lookup.
        let v = map.get(&k);

        // Turn `Option<&i64>` into `Option<i64>`.
        v.cloned()
    }
}

fn main() {
    let mut map = HashMap::new();
    map.insert(("a".to_owned(), "b".to_owned()), 2);
    map.insert(("c".to_owned(), "d".to_owned()), 3);

    let a = "a".to_owned();
    let b = "b".to_owned();
    println!("{:?}", get(map, &a, &b));
}

```

---

_[View the full topic](https://users.rust-lang.org/t/hashmap-with-tuple-keys/12711)._
