Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: string.split() tuloksia ei voi verrata

Tampio [08.04.2008 22:52:50]

#

Kun pilkon esim seuraavan merkkijonon osiin split metodilla, niin saatuja merkkijonoja verratessa ne eivät täsmää itsensä kanssa näennäisesti identtisiin merkkijonoihin.

String[] x = "eka toka".split("\\s");

Nyt siis jos tulostan x[1] sisällön näytölle, niin näkyviin tulee ihan oikein "toka", mutta jos vertaan (x[1] == "toka"), niin tuo ei pidäkkään paikkaansa.
Mistä tuo johtuu tai mitä olen missannut?

Sami [08.04.2008 23:01:00]

#

Käytä merkkijonojen vertailuun equals-metodia. ==-operaattori vertailee vain sitä ovatko oliot samoja, ei sitä onko niiden sisältö "sama".

Esimerkkejä:

String a = "foo";
String b = "foo";
String c = a;
String d = "bar";

if (a == b) {
// Palauttaa false, koska a ja b ovat eri olioita.
}

if (a == c) {
// Palauttaa true, koska a ja b ovat viittaukset samaan olioon.
}

if (a.equals(b)) {
// Palauttaa true, koska "foo" on yhtä kuin "foo".
}

if (a.equals(c)) {
// Palauttaa true, koska "foo" on yhtä kuin "foo".
}

if (a.equals(d)) {
// Palauttaa false, koska "foo" ei ole sama kuin "bar".
}

Tampio [09.04.2008 09:14:36]

#

Dodii, kiitos.

Jackal von ÖRF [09.04.2008 10:17:17]

#

Sami kirjoitti:

String a = "foo";
String b = "foo";

if (a == b) {
// Palauttaa false, koska a ja b ovat eri olioita.
}

Paitsi kun merkkijonovakiot on määritelty saman luokan sisällä. Silloin kääntäjä optimoi, että molemmat vakiot ovat viitteitä samaan olioon. Jos Stringit tuotetaan dynaamisesti (esim. new String("foo") tai mainittu split-metodi), niin sitten ne ovat oikeasti eri olioita. Eli joskus == voi sattumalta toimia, mutta siihen ei pidä koskaan luottaa.

FooBat [26.04.2008 03:39:59]

#

Jackal von ÖRF kirjoitti:

Sami kirjoitti:

String a = "foo";
String b = "foo";

if (a == b) {
// Palauttaa false, koska a ja b ovat eri olioita.
}

Paitsi kun merkkijonovakiot on määritelty saman luokan sisällä. Silloin kääntäjä optimoi, että molemmat vakiot ovat viitteitä samaan olioon. Jos Stringit tuotetaan dynaamisesti (esim. new String("foo") tai mainittu split-metodi), niin sitten ne ovat oikeasti eri olioita. Eli joskus == voi sattumalta toimia, mutta siihen ei pidä koskaan luottaa.

Ei taida olla suoranaisesti kääntäjän optimointi vaan java virtuaalikoneen käyttämän String toteutuksen ominaisuus. Java käyttää Stringien optimoimiseen string pool toteusta eli ohjelmassa esiintyvät merkkijonovakiot taulukoidaan, jotta samanlaiselle merkkijonolle voidaan antaa sama muistiosoite. Myös itsemuodostetut merkkijonot voidaan lisätä pooliin String-luokan intern()-metodilla.
Esim.

String f = "foo";
String b = "bar";
String fb = "foobar";

System.out.println(f+b == fb);
System.out.println((f+b).intern() == fb);

Yleisesti siis kannattaa kuitenkin käyttää equals()-metodia merkkijonojen vertailuun. Ainoa huono puoli siinä tosin on, että pitää aina muistaa erikseen tarkistaa, että ensimmäinen vertailtava merkkijono ei ole null.

Tietyissä tilanteissa kuitenkin intern():n käyttö on ihan hyvä optimoitikikka muistinkulutuksen ja nopeuden suhteen (voidaan käyttää == operaattoria, kun kaikki samanlaiset merkkijonot ovat oikeasti samassa osoitteessa.)

String: intern() kirjoitti:

Returns a canonical representation for the string object.

A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta