Is a string
key faster than a int
key in a Dictionary<,>
?

- 773
- 4
- 10
- 22
-
3How did you determine that key performance is important in your application? Do not do premature optimizations. – jgauffin Apr 21 '11 at 11:36
-
2First and foremost, decide what to store in the dictionary. Then, much later, if you decide you have a performance problem, measure your programs performance, pinpoint the topmost candidate for optimization, and start there. It is unlikely that your current question will have much of an impact, except for perhaps you using the wrong data type all over the place "in the name of performance". – Lasse V. Karlsen Apr 21 '11 at 11:44
-
2If your int keyspace is limited you can sometimes get away with a `T[]` and use the indexer as key, which uses up more memory but is quite a bit faster than using a dictionary. – Sam Saffron May 29 '11 at 08:47
-
1never even considered this as an issue. If the design says I need to map string => xx then thats what I do. I am sure that adding magic to do string -> magic -> int => x will be slower (If not then .net dictionary team would have already done it) – pm100 Aug 22 '18 at 22:55
-
[Not in Python](https://stackoverflow.com/a/8403754/5033247) – Smart Manoj Dec 16 '20 at 04:49
3 Answers
No. First of all, Dictionary
[UPDATED] uses hash code of the keys to find them in its internal storage - rather than the keys. And Hashcode is an int
. For int
, it is just the value of the int
, for string
it has to be generated.
So using int
is slightly faster.
In fact generating hash code for a string is a pretty complex process (snippet using Reflector) [Hope this is not taken as copyright breach because it is NOT]:
fixed (char* str = ((char*) this))
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*) chPtr;
for (int i = this.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
numPtr += 2;
}
return (num + (num2 * 0x5d588b65));
}

- 80,612
- 21
- 160
- 208
-
5A dictionary stores the keys as well, but it uses the hash code to determine where to store them. Slightly inaccurate answer. – Lasse V. Karlsen Apr 21 '11 at 11:41
-
1Yes. Silly me... I will update it. I meant in order to retrieve the values. – Aliostad Apr 21 '11 at 11:42
-
But I agree with you that int is *slightly* faster, due to the fact that there is no calculation to perform, such as the one the `string.GetHashCode()` method has to do. – Lasse V. Karlsen Apr 21 '11 at 11:43
-
its not secret - heres the link https://referencesource.microsoft.com/#mscorlib/system/string.cs,501774d5676172e1 – pm100 Aug 22 '18 at 22:50
-
-
I know this is pretty old and answered question, so this answer for everybody who look for it in future. Also for me it was interesting question and I tried to find practical answer to this question, and result is pretty interesting.
Generally String as key is much slower than int as key.
Code:
class Program
{
object obj = new object();
Dictionary<long, object> longDict = new Dictionary<long, object>();
Dictionary<string, object> stringDict = new Dictionary<string, object>();
public static void Main(string[] args)
{
Program hash = new Program();
hash.Test(1000);
hash.Test(10000);
hash.Test(100000);
hash.Test(1000000);
hash.Test(10000000);
Console.Read();
}
private void Test(int iterations)
{
Console.WriteLine(String.Format("Test for {0} iterations", iterations));
longDict.Clear();
stringDict.Clear();
for (int i = 0; i < iterations; i++)
{
longDict.Add(i, obj);
}
for (int i = 0; i < iterations; i++)
{
stringDict.Add(i.ToString(), obj);
}
IntTest(iterations);
StringTest(iterations);
}
private void IntTest(int iteraions)
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
object test;
for (int i = 0; i < iteraions; i++) {
test = longDict[i];
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
}
private void StringTest(int iteraions)
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
object test;
for (int i = 0; i < iteraions; i++)
{
test = stringDict[i.ToString()];
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
}
}
Result:

- 349
- 4
- 16
-
6You should somehow exclude time of unrelated "i.ToString()" operations from results for Dictionary
. – Vlad Rudenko Jul 06 '20 at 08:53 -
1WARNING: These results are misleading, and therefore worse than useless. PROBLEMS: 1: Time is spent by `i.ToString()` . 2: The strings are very short. 3: Dictionary sizes differ (cache hit/miss). (Make large dictionaries and re-use them.) 4: Retrieved elements must not be immediately discarded (compiler-optimizations). 5: Should also test for keys of `int`, not just `long`. 6: The first batch of runs should be ignored because of JIT. 7: Three parameters needed: `(nIterations, nElements, stringLength)` – Jan Heldal May 27 '21 at 08:26
-
I removed the i.ToString() and cached the values like here: https://gist.github.com/juanpaexpedite/757e3b15dbdf5cb52453c7fe42effacf . I tested and storing the in hash is better than storing string keys unless I am doing something not performant. – Juan Pablo Garcia Coello Aug 29 '21 at 07:26
-
I am with magabobik. Just for removing the impact of i.ToString()
. I changed the following in his code. but still Int is much faster.
replace longDict.Add(i, obj);
with longDict.Add(int.Parse(i.ToString()), obj);
result
Test for 1000 iterations
Time elapsed: 00:00:00.0000164
Time elapsed: 00:00:00.0002208
Test for 10000 iterations
Time elapsed: 00:00:00.0001618
Time elapsed: 00:00:00.0022131
Test for 100000 iterations
Time elapsed: 00:00:00.0016835
Time elapsed: 00:00:00.0429761
Test for 1000000 iterations
Time elapsed: 00:00:00.0318415
Time elapsed: 00:00:00.3557074

- 2,623
- 2
- 25
- 24
-
1Why would you replace `longDict.Add(i, obj)` with `longDict.Add(int.Parse(i.ToString(), obj)` though? The others meant `test = stringDict[i.ToString()];` that `ToString()` :) – Raid May 03 '23 at 05:29