JavaのObject.hashCodeは結構衝突する件

Posted on 2010-10-07 by takezoux2

Hash値の計算手抜きしてObject.hashCode使ってたけど、どうも衝突が発生している疑惑があったので、確かめてみました。結果としては、かなり衝突するということがわかりました。きちんとMD5とかSHAとか使ったほうがいいですねw

テスト

ランダムな20~30文字の小文字アルファベットの文字列からhashCodeを計算し、Hash値の衝突数を調べる

テストに使ったコード

import java.util.Random

object Main{

    def main(args : Array[String]) = {

        var m : Map[Int,String] = Map()
        var conflict = 0

        def check = {
            val s = randomString
            val hashCode = s.hashCode
            if(m.contains(hashCode)){
                if(m(hashCode) != s){
                    println("Find same hashCode: " + s + " and " + m(hashCode))
                    conflict += 1
                }
            }else{
                m = m +( hashCode -> s)
            }
        }

        val repeat = if(args.length > 0) args(0).toInt else 100

        (0 until repeat).foreach( _ => check)

        println("%s / %s conflics".format(conflict,repeat))

    }
    val r = new Random
    def randomString = {
        val chars = r.nextInt(10) + 20
        (0 to chars).foldLeft("")( (s,i) => { s + ('a' + r.nextInt(26)).asInstanceOf[Char]})
    }
}

実行結果

>scala Main 100000
0 / 100000 conflics

>scala Main 100000
Find same hashCode: uzaiwypnpcglgjkmfuquogkil and exxjmayuwoperjewrffssstxj
Find same hashCode: zxucborhherxalztzlzzdccikx and zcaofzchrqfmpyxkodxnx
2 / 100000 conflics

>scala Main 100000
Find same hashCode: krjrsrqyhyejdcrouwmphppwiph and mwjaeywvamrxcyvwzdmlnm
1 / 100000 conflics

>scala Main 200000
Find same hashCode: qmwgtgphfadgpuqwdjvbcfwqtdxkt and adwaorxslxsojnkrcxvnchvh
Find same hashCode: dncdgmwvrbuzvlhexgawrqqcs and bcutmsquxuawdsvhnicygxzijmsf
Find same hashCode: njnokarumjoqgoelirwjeuzkqfj and smavuvcorkdkbjeywqpvmvcnsan
Find same hashCode: cyylhuovroawzitfxbellruqam and yznsmzvgcqzwfbgewbupblsuicflzo
4 / 200000 conflics


Tags

Scala Tips