# Using \`DataType\` as key in \`Dict\`

**URL:** https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796
**Category:** General Usage
**Created:** [October 22, 2020, 5:09am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796 "2020-10-22T05:09:50Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [October 22, 2020, 5:09am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/1 "2020-10-22T05:09:50Z")

</div>

Hi all,

Just a quick question: Is it a bad idea to use `DataType` as the key in a `Dict` if performance is reasonably important? So, something like this:

```julia
struct MyType ; end
d = Dict(Float64=>"a", MyType=>"b")

```

Using `BenchmarkTools`, recovering items from this dictionary is about 3 times slower than using `Int` for the key, which is fast enough for my application. But is there some other reason why this is a bad idea? I don’t really understand how `DataType` is represented “under-the-hood”, so thought it worth asking. Apologies if this is a stupid question.

**EDIT:** I’ve done a bit more thinking, and for the problem I’m working on it seems like a useful storage technique would be to map specific types to instances of that type. So something like this:

```julia
struct MyType1 ; x::Float64 ; end
struct MyType2 ; x::Float64 ; end
d = Dict(MyType1=>MyType1(1.0), MyType2=>MyType2(2.0))

```

Any thoughts on whether this is a terrible idea? BTW the reason I’m not just storing the instances in a `Vector` is that I want to be able to look up quickly whether a particular type is in the collection, and that would take much longer in a long vector than in a dictionary.

Cheers,

Colin

---

<div class="post-metadata">

### Author: ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)
#### Post date: [October 22, 2020, 8:46am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/2 "2020-10-22T08:46:55Z")

</div>

If this is what you need now, I don’t see any reason to avoid `DataType` keys. It will be slower than `Int` keys as you noted (hashing and equality testing is slower), but still reasonably fast, so you shouldn’t worry until this become a bottleneck.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [October 22, 2020, 12:23pm UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/3 "2020-10-22T12:23:50Z")

</div>

You should probably check out `IDDict`. That should be much faster. (I think there might be some differences in results, but only for weird types)

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [October 22, 2020, 12:32pm UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/4 "2020-10-22T12:32:00Z")

</div>

One example, where comparing by id and by `isequal` ~~/`hash`~~ differs is this:

```julia
julia> Tuple{Union{Int,UInt}} === Union{Tuple{Int},Tuple{UInt}}
false

julia> isequal(Tuple{Union{Int,UInt}}, Union{Tuple{Int},Tuple{UInt}})
true

```

That might be fine for your specific usecase, but depending on what you want to do with this, it could be important to treat these as the same type.

Edit:  
Their hash is actually still different:

```julia
julia> hash(Tuple{Union{Int,UInt}}) == hash(Union{Tuple{Int},Tuple{UInt}})
false

```

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [October 22, 2020, 7:26pm UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/5 "2020-10-22T19:26:53Z")

</div>

> [@simeonschaub](#):
>
> Their hash is actually still different:

That’s a bug.

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [October 23, 2020, 12:38am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/6 "2020-10-23T00:38:13Z")

</div>

Okay great, thanks for responding.

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [October 23, 2020, 12:43am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/7 "2020-10-23T00:43:50Z")

</div>

Interesting. Perhaps I’ve misunderstood the use-case of `IdDict`. I thought `IdDict` was a good choice when the key was large in terms of the number of bytes it occupies, like a long vector of numbers, since only the object id needs to be hashed, rather than the entire vector of numbers. But in this situation, my keys won’t be large since they are all `DataType` (I think instances of `DataType` are small but I don’t actually know for sure).

Having said that, it does look like there is a 20% speed-up on lookup using an `IdDict` using the following (admittedly very simple) example:

```julia
julia> using BenchmarkTools

julia> d1 = Dict(Float64=>"a", Int=>"b");

julia> d2 = IdDict(Float64=>"a", Int=>"b");

julia> @btime $d1[Int] ;
  15.056 ns (0 allocations: 0 bytes)

julia> @btime $d2[Int] ;
  12.176 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [October 23, 2020, 12:45am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/8 "2020-10-23T00:45:18Z")

</div>

Fortunately I don’t think I need to worry about odd corner cases like this one.

Interesting though. And good job on finding a bug 🙂

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [October 23, 2020, 12:46am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/9 "2020-10-23T00:46:26Z")

</div>

An `IdDict` doesn’t use the hash of the ID. it uses the ID itself. In addition to the semantic change (equality vs identity), this means that you don’t have to compute a hash value at all.

---

<div class="post-metadata">

### Author: ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)
#### Post date: [October 23, 2020, 3:57am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/10 "2020-10-23T03:57:56Z")

</div>

Ah I see. Thanks for the info it was helpful. I’ll probably end up using `IdDict`.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [October 23, 2020, 5:53am UTC](https://discourse.julialang.org/t/using-datatype-as-key-in-dict/48796/11 "2020-10-23T05:53:40Z")

</div>

Well, the ID is a hash.
