Nuoseklumas hashCode () yra Java eilutėje

„Java hashCode“ vertė apskaičiuojama kaip: ( String.hashCode () ):

 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 

Ar yra kokių nors aplinkybių (pavyzdžiui, JVM versija, paslaugų teikėjas ir tt), pagal kurią ši išraiška bus vertinama kaip klaidinga?

 boolean expression = "This is a Java string".hashCode() == 586653468 

Atnaujinimas Nr. 1: Jei sakote, kad atsakymas yra „taip, yra tokių aplinkybių“, tada pateikite konkretų pavyzdį, kai „Tai yra Java eilutė“ .hashCode ()! = 586653468. Pabandykite kaip įmanoma konkretesnis / konkretesnis.

Atnaujinimas Nr. 2: visi žinome, kad, remiantis „hashCode“ () įgyvendinimo detalėmis, paprastai yra blogai. Tačiau kalbu konkrečiai apie String.hashCode () - todėl prašome atsakyti į String.hashCode (). Object.hashCode () visiškai nesusijęs su šio klausimo kontekstu.

119
24 апр. nustatyta 24 d. 2009-04-24 12:11 '09, 12:11 2009-04-24 12:11
@ 7 atsakymai

Matau šią dokumentaciją „Java“ 1.2.

Tiesa, kad apskritai neturėtumėte pasikliauti maišos kodo įgyvendinimu, o likęs toks pats, dabar dokumentavo java.> elgesį, todėl jo keitimas bus laikomas esamų sutarčių pažeidimu.

Jei įmanoma, neturėtumėte pasikliauti maišos kodais, tuo pat metu palikdami tą patį skirtingose ​​versijose ir tt, bet, mano nuomone, java.> yra ypatingas atvejis, nes algoritmas yra nurodytas ... tol, kol esate pasiruošę prieš nustatant algoritmą atsisakoma suderinamumo su išleidimais.

83
24 апр. Atsakyti Jon Skeet balandžio 24 d 2009-04-24 12:25 '09, 12:25, 2009-04-24 12:25

Radau kažką apie JDK 1.0 ir 1.1 ir> = 1.2:

JDK 1.0.x ir 1.1.x hashCode funkcija ilgoms eilutėms, apdorotoms imant kiekvieną n-ąjį ženklą. Tai yra gana gera, kad jūs turėsite daug maišymo stygų tokiu pačiu verte, taip sulėtindami Hashtable. JDK 1.2 funkcija pagerinta, kad rezultatas būtų padaugintas iki 31, tada pridėkite sekantį simbolį. Tai šiek tiek lėčiau, bet daug geriau vengia susidūrimų. Šaltinis: http://mindprod.com/jgloss/hashcode.html

Kažkas kita, nes jums atrodo, kad reikia skaičiaus: kaip naudoti CRC32 ar MD5 vietoj maišos kodo, ir jūs gerai einate - jokios diskusijos ir jokių rūpesčių visai ...

18
24 апр. atsakymą pateikė ReneS 24 d. 2009-04-24 15:17 '09, 15:17, 2009-04-24 15:17

Jūs neturėtumėte pasikliauti maišos kodu, atitinkančiu konkrečią vertę. Tik tuo atveju, jei bus grąžinti nuoseklūs rezultatai to paties vykdymo metu. API dokumentuose nurodyta:

Bendra hashCode sutartis:

  • Kai tą patį objektą skambina daugiau nei vieną kartą vykdant „Java“ programą, hashCode metodas turi nuosekliai grąžinti tą patį sveikąjį skaičių, jei vienodais lyginamaisiais duomenimis su objektu naudojama informacija nepasikeičia. Šis sveikasis skaičius neturėtų likti suderintas su vienu paraiškos vykdymu kitam tos pačios programos vykdymui.

KEITIMAS Kadangi javadoc už String.hashCode () nurodo, kaip apskaičiuojamas String hash kodas, bet koks jo pažeidimas gali pažeisti viešąją API specifikaciją.

9
24 апр. Martin OConnor atsakymas, pateiktas balandžio 24 d 2009-04-24 12:16 '09, 12:16, 2009-04-24 12:16

Kaip jau minėta, apskritai neturėtumėte pasikliauti klasės maišos kodu, kuris lieka tas pats. Atkreipkite dėmesį, kad net vėlesni tos pačios programos veiksmai toje pačioje virtualioje mašinoje gali sukurti skirtingas maišos reikšmes. „AFAIK“ „Sun JVM“ funkcija apskaičiuoja tą patį maišą kiekviename eiga, tačiau tai negarantuojama.

Atkreipkite dėmesį, kad tai nėra teorinė. „Jagu.>buvo pakeista JDK1.2 (senas maišas turėjo problemų su hierarchinėmis eilutėmis, pvz., URL ar failų pavadinimais, nes jis buvo linkęs sukurti tą patį maišą eilutėms, kurios tik skyrėsi ).

java.>

4
24 апр. atsakymas pateikiamas 24 val. 2009-04-24 12:23 '09, 12:23, 2009-04-24 12:23

Kita problema (!) Verta nerimauti dėl galimų ankstyvųjų / vėlyvųjų „Java“ versijų įgyvendinimo pokyčių. Nemanau, kad įgyvendinimo detalės nustatomos akmenimis, todėl potencialus naujinimas į būsimą „Java“ versiją gali sukelti problemų.

Apatinėje eilutėje nenoriu pasikliauti hashCode() .

Galbūt jūs galite nurodyti, kokią problemą bandote išspręsti naudodamiesi šiuo mechanizmu, ir tai akcentuos tinkamesnį požiūrį.

3
24 апр. Brian Agnew atsakymas, pateiktas balandžio 24 d 2009-04-24 12:16 '09, 12:16, 2009-04-24 12:16

Tiesiog atsakykite į jūsų klausimą ir nekelkite jokių diskusijų. Apache Harmony JDK diegimas, atrodo, naudoja kitą algoritmą, bent jau atrodo visiškai kitoks:

„Sun jdk“

 public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; } 

Harmonija apache

 public int hashCode() { if (hashCode == 0) { int hash = 0, multiplier = 1; for (int i = offset + count - 1; i >= offset; i--) { hash += value[i] * multiplier; int shifted = multiplier << 5; multiplier = shifted - multiplier; } hashCode = hash; } return hashCode; } 

Nedvejodami patikrinkite save ...

3
24 апр. atsakymą pateikė ReneS 24 d. 2009-04-24 14:21 '09, 14:21, 2009-04-24 14:21

Jei nerimaujate dėl pokyčių ir galbūt nesuderinamų virtualių mašinų, paprasčiausiai nukopijuokite esamą „hashcode“ diegimą į savo naudingumo klasę ir naudokite tai, kad generuotumėte savo maišos kodus.

2
24 апр. atsakymą Sam Barnum pateikė balandžio 24 d 2009-04-24 18:27 '09, 18:27, 2009-04-24 18:27

Kiti klausimai apie „ žymių arba „ Užduoti klausimą“