What is a sensible prime for hashcode calculation?

后端 未结 6 764
故里飘歌
故里飘歌 2020-11-29 16:27

Eclipse 3.5 has a very nice feature to generate Java hashCode() functions. It would generate for example (slightly shortened:)

class HashTest {
    int i;
           


        
相关标签:
6条回答
  • 2020-11-29 16:34

    I recommend using 92821. Here's why.

    To give a meaningful answer to this you have to know something about the possible values of i and j. The only thing I can think of in general is, that in many cases small values will be more common than large values. (The odds of 15 appearing as a value in your program are much better than, say, 438281923.) So it seems a good idea to make the smallest hashcode collision as large as possible by choosing an appropriate prime. For 31 this rather bad - already for i=-1 and j=31 you have the same hash value as for i=0 and j=0.

    Since this is interesting, I've written a little program that searched the whole int range for the best prime in this sense. That is, for each prime I searched for the minimum value of Math.abs(i) + Math.abs(j) over all values of i,j that have the same hashcode as 0,0, and then took the prime where this minimum value is as large as possible.

    Drumroll: the best prime in this sense is 486187739 (with the smallest collision being i=-25486, j=67194). Nearly as good and much easier to remember is 92821 with the smallest collision being i=-46272 and j=46016.

    If you give "small" another meaning and want to be the minimum of Math.sqrt(i*i+j*j) for the collision as large as possible, the results are a little different: the best would be 1322837333 with i=-6815 and j=70091, but my favourite 92821 (smallest collision -46272,46016) is again almost as good as the best value.

    I do acknowledge that it is quite debatable whether these calculation make much sense in practice. But I do think that taking 92821 as prime makes much more sense than 31, unless you have good reasons not to.

    0 讨论(0)
  • 2020-11-29 16:35

    I just want to point out that hashcode has nothing to do with prime. In JDK implementation

    for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
    

    I found if you replace 31 with 27, the result are very similar.

    0 讨论(0)
  • 2020-11-29 16:36

    I'd choose 7243. Large enough to avoid collissions with small numbers. Doesn't overflow to small numbers quickly.

    0 讨论(0)
  • 2020-11-29 16:40

    Actually, if you take a prime so large that it comes close to INT_MAX, you have the same problem because of modulo arithmetic. If you expect to hash mostly strings of length 2, perhaps a prime near the square root of INT_MAX would be best, if the strings you hash are longer it doesn't matter so much and collisions are unavoidable anyway...

    0 讨论(0)
  • 2020-11-29 16:41

    You need to define your range for i and j. You could use a prime number for both.

    public int hashCode() {
       http://primes.utm.edu/curios/ ;)
       return 97654321 * i ^ 12356789 * j;
    }
    
    0 讨论(0)
  • 2020-11-29 17:00

    Collisions may not be such a big issue... The primary goal of the hash is to avoid using equals for 1:1 comparisons. If you have an implementation where equals is "generally" extremely cheap for objects that have collided hashs, then this is not an issue (at all).

    In the end, what is the best way of hashing depends on what you are comparing. In the case of an int pair (as in your example), using basic bitwise operators could be sufficient (as using & or ^).

    0 讨论(0)
提交回复
热议问题