Hali!
Meg tudná valaki magyarázni, hogy miért ajánlják mindenhol a == használatát az intern-ált (lol) Stringek megemlítésekor?
Értem, hogy gyorsabb, mert referenciát hasonlít össze, és nem karakterről-karakterre két sztringet, de nem ugyanúgy if (this==s) return true; -val kezdődik a String-ben az equals(String s)?
üdv,
- 1631 megtekintés
Hozzászólások
Lehet, hogy ott ahol ezt alkalmazták, kifejezetten azt szerették volna tudni, hogy ugyanarról az objektumról van-e szó, és nem azt, hogy karakterről karakterre megegyezik-e a két string. Valahogy biztos ki lehet deríteni, hogy tényleg ez volt-e a szándéka a programozónak vagy hibázott.
- A hozzászóláshoz be kell jelentkezni
Arról van szó, hogy már a második, egyébként jó Java-s könyvben olvasok az intern-ált stringekről.
Szépen, világosan elmondja, hogy ez h működik. Eddig ok, de aztán még azt is kifejti, h ha sok összehasonlítást végzünk, akkor intern-áljuk, és utána használjuk a == operátort, mert az intern-álás miatt a referenciájuk is meg fog egyezni a stringeknek, aminek az összehasonlítása tényleg nagyságrenddel gyorsabb, mint a karakterről-karakterre való vizsgálat.
Viszont az eqals implementációja úgyis azzal kell kezdődjön, hogy először ezt ellenőrzi?!
- A hozzászóláshoz be kell jelentkezni
De ha a gyorsaság a szempont, akkor az == operátor tényleg gyorsabb a equals-nál is, hiszen a függvényhívással járó idő is elmarad. Gondolom a gyorsaság még továbi növelése miatt használják.
- A hozzászóláshoz be kell jelentkezni
Nem hiszem, hogy azzal kezdődik. De ha biztosan akarod tudni, akkor nézd meg a forrást.
- A hozzászóláshoz be kell jelentkezni
Elég logikusnak tűnik, hogy azzal kezdődjön.
- A hozzászóláshoz be kell jelentkezni
Nagy amatőrségre utal, ha valaki nem
if (a==null) return false;
if (a==this) return true;
-val kezd egy equals(a) implementációt...
- A hozzászóláshoz be kell jelentkezni
Speciell amit te írtál, az nem "a==this"-szel kezdődik.
De közben kiderült (ld. lejjebb), hogy semmilyen más ellenőrzés nincs az "a==this" előtt.
- A hozzászóláshoz be kell jelentkezni
Mert minek ? Kivaloan tud hibat dobni, plusz kod irasa nelkul is :)
- A hozzászóláshoz be kell jelentkezni
Szerintem arrol lehet szo, hogy igy megsporolhatsz egy fuggvenyhivast, mert a JITtelt kodban egy-az-egyben lehet egy referencia compare ahelyett, hogy fel kellene epiteni egy exec stacket, etc.
Tehat
if (a == b)
=>
load address a
load address b
cmp
branch if true ...
if (a equals b)
load address a
load address b
call virtual method equals
branch if true ...
(bocs a pszeudokodert, a java bytecode opokat nem ismerem)
while (!sleep) sheep++;
- A hozzászóláshoz be kell jelentkezni
Ezzel egyetértek. Csak egy függvényhívást nem szokták költségnek számolni (legalábbis egy átlagos OO program írása során).
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy nem szokták, de az.
- A hozzászóláshoz be kell jelentkezni
Ez szarvas hiba.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
Ez igaz, de itt minimum 10x-es kulonbsegrol van szo. :)
while (!sleep) sheep++;
- A hozzászóláshoz be kell jelentkezni
Megnéztem a forrást, valóban így kezdődik:
(...)
1012 public boolean equals(Object anObject) {
1013 if (this == anObject) {
1014 return true;
1015 }
(...)
--
The Net is indeed vast and infinite...
http://gablog.eu
- A hozzászóláshoz be kell jelentkezni
Talán azért, hogy emlékeztessen, hogy ez egy internált String. ;)
String a = "valami";
String b = a;
boolean bool = true;
long startTime;
startTime = System.currentTimeMillis();
for(int i=0;i<100000000;i++) {
bool = bool && a == b;
}
System.out.println((System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
for(int i=0;i<100000000;i++) {
bool = bool && a.equals(b);
}
System.out.println((System.currentTimeMillis() - startTime));
Az elvetemült példa eredménye:
597
2062
Nem mintha számítana valós környezetben…
- A hozzászóláshoz be kell jelentkezni
De mi van, ha van két, egymástól függetlenül létrehozott String objektumom, és mindegyik tartalma "alma".
Ekkor a == false-t fog visszaadni, mert enm ugyan az a referencia.
Ekkor csak az equals() segít, ha meg akarom tudni, hogy ugyan azt a szöveget tartalmazzák-e.
- A hozzászóláshoz be kell jelentkezni
Szerintem erre vagy kiváncsi: a String osztály kezel egy privát elérésű "string-pool"-t. Ha meghívod az intern függvényt a stringeden, akkor az megnézi, hogy a poolban szerepel-e mar a string (equals-szal), es ha igen, akkor erre a stringre ad egy referenciát, ha nem akkor beteszi a poolba az aktuális stringet, és erre való referenciát ad vissza. Ezért két equals alapján azonos string ha intern-álod, akkor referencia alapján is azonos lesz. Gondolom ez arra jó, hogy ha sokszor kell összehasonlítást végezned, akkor először intern-álsz, és utána elég referencia szerint vizsgálnod.
- A hozzászóláshoz be kell jelentkezni
Ilyenkor viszont két különböző változónévvel ellátott, de azonos tartalmú, ezáltal azonos referenciájú, string valamelyikének megváltoztatása magával vonja a másik megváltozását is, amit nem biztos, hogy úgy akartuk. Intern-áláskor tehát nagyon kell vigyázni a stringek módosítgatásával!
- A hozzászóláshoz be kell jelentkezni
Mit módosítgatnál rajta?
String s1 = "lofasz";
String s2 = s1;
s1 = "alma";
System.out.println(s2); // ugye nem arra gondolsz, hogy itt almat irna ki?
Mellesleg ezek nem C típusú pointerek, hogy csak úgy beleírj.
- A hozzászóláshoz be kell jelentkezni
Nem erre gondoltam, hanem az intern-álás utáni állapot esetére!
String s1 = "valami";
String s2 = s1.intern();
String s3 = s1.intern();
s2 = s2 + " + még valami";
System.out.println(s3);
De kipróbáltam, ekkor sem lesz egyenlő s2 és s3. De ezt már nem értem, miért nem.
Úgyhogy az előző hozzászólásomat vissza kell szívnom! Bocs!
- A hozzászóláshoz be kell jelentkezni
Ez (s2 = s2 + " + még valami") a sor az alábbinak felel meg:
s4 = s2 + " + még valami";
s2 = s4;
azaz létrejön egy új string, és s2 végül erre fog mutatni.
ha megnézed a string osztályt az összes függvénye "const", azaz soha nem
módosítják az adott objektum értékét, hanem visszatérési értékként egy új objektumot példányosítanak.
pl a concat így néz ki:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
Azaz akármit csinálhatsz a Stringgel intern() hívás után, csak tudnod kell, hogy az egy másik String lesz ... :)
- A hozzászóláshoz be kell jelentkezni
Kösz szépen az infót!
- A hozzászóláshoz be kell jelentkezni
Ez is nagyon hasznos. Kösz!
- A hozzászóláshoz be kell jelentkezni