Java programozás 15. – String

String, avagy minden, amit begépelhetsz (vagy nem)

A Java programozási nyelvben, mint megtudhattad, többféle változótípus létezik. Ezek egy része egyszerű (primitív) típus, de vannak összetett, komplexebb típusok, ezek minden esetben objektumok. Ezek egyike a karakterlánc, más nevén String.

Mint a neve is mutatja, ez egy osztály. Ez honnan látszik? Nagy kezdőbetűvel írtam a nevét. Nem csak én, már az alap program main programrészében is láthattad számtalanszor:

public static void main( String[] args )

A Stringek karakterekből állnak, melyek egymás után meghatározott sorrendben karakterláncot alkotnak. A Stringek nem csak kiíratható karaktereket tartalmazhatnak, olyanok is lehetnek benne, amelyek nem látszanak, ezekről majd később szót ejtek.

String deklaráció és értékadás

A String deklarációja a következőképpen néz ki:

String s;

A Stringnek meglehetősen sokféle módon adható kezdőérték, ebből lássunk egyet, igaz, ez a forma nem túl gyakori, létrehozok egy s nevű Stringet:

String s = new String();

Létrehoztam egy új, üres Stringet. Ezt mondjuk gyakran nem így használjuk. A new kulcsszóval egy új objektumot tudok létrehozni, ami az adott osztályból egy új példány. Az előző, tömbökről szóló anyag után ez már nagy meglepetést talán nem jelent, hiszen ott is ilyesmit írtunk, de a new-ról és szerepéről az Osztályok és objektumok témakörben olvashattál részletesebben. A String mérete is állandó, csakúgy, mint a tömböké.

A String a Java nyelvben megváltozhatatlan!

Ha egyszer beállítottad az értékét, akkor az attól kezdve mindig ugyanaz marad. Nézzünk akkor pár másik értékadási lehetőséget:

String s1 = "abcd";

char data[] = {'a', 'b', 'c'};
String str = new String(data);

String str2 = new String("xyz"); // ezt azért kerüljük..

String s2 = s1 + "efgh";

Az első esetben a String formai megjelenésének megfelelően adok meg egy értéket. A második esetben létrehozok egy karakterekből álló tömböt, amit odaadok a new-val létrehozandó String objektumnak, hogy abból állítsa elő magát. A harmadik esetben szinten new-val hozok létre egy új String objektumot, és odaadom neki egy literálként azt a karakterláncot, ami a tartalma legyen. Az utolsó példában egy Stringet egy másik bővítésével hozok létre, itt a + operátor mint az összefűzés műveleti jele szerepel.

A következő példa kicsit fura lehet:

String s = "abcd";
System.out.println( s ); // abcd

s += "efgh";
System.out.println( s ); // abcdefgh

Azt mondtam, hogy a String megváltoztathatatlan. Itt mégis hozzáfűztem valamit és az s-nek látszólag tényleg megváltozik a tartalma. És még működik is! Igen ám, de a háttérben nem ez történik:

  1. Létrehozunk egy String objektumot, beállítjuk a kezdőértékét, és a címét hozzárendeljük az s változóhoz.
  2. Amikor az s-hez hozzáfűzünk valamit, létrejön egy új String objektum a háttérben.
  3. Ennek értéke az eredeti String objektum tartalma és az “efgh” literál összefűzéséből kialakított karakterlánc lesz.
  4. Az s változóhoz az új objektum címe lesz hozzárendelve.
  5. Az eredeti s-hez rendelt objektum meg változó nélkül marad, hiszen a változóhoz már egy új címet rendeltünk.
  6. A változóhoz nem rendelt objektumot emiatt hamarosan kitakarítják a kupacból (de addig is foglalja a memóriát!)

Speciális String literálok

Amikor egy Stringnek értéket szeretnénk adni, léteznek bizonyos speciális karakterek. Ezek megadásához szükségünk lehet a backslash karakterre, ami a \ (visszaper jel). Ezen speciális karakterekre példa:

  1. \n (sordobás)
  2. \t (tabulátor)
  3. \” (idézőjel karakter)
  4. \\ (maga a backslash karakter)

Mi van akkor, ha a Stringben szeretnék idézőjeleket megjeleníteni?

Michael "Air" Jordan

Ebben az esetben a következő dolgot tehetjük:

String s = "Michael \"Air\" Jordan\n";

Itt a normál módon megadott idézőjelek a literál elejét és végét jelentik. Viszont a Stringben szeretnénk idézőjelet szerepeltetni, ezért a backslash (kivétel) karaktert tesszük elé, így tudni fogja a Java, hogy az Air szó előtti és utáni idézőjelek nem a String határait jelzik, hanem a String részei! A végén a \n pedig egy sordobást tesz a név végére.

És mi van akkor, ha magát a \ karaktert szerepeltetnénk a Stringben? Önmaga hogy lesz kivétel? Ezt szeretnénk megjeleníteni:

Gondolkodom, tehat vagyok. \Descartes\

Itt a String része lenne az a karakter, amivel a kivételeket szoktuk jelezni, de itt önmagát akarjuk megjeleníteni. Akkor hogy oldjuk meg, hogy a \ jelet a String részeként kezelje? Ekkor a következő a teendő:

String s = "Gondolkodom, tehat vagyok. \\Descartes\\";

Egyszerűen a \ jel elé kell egy másik, ami ezáltal önmagát teszi kivétellé. És mi van akkor, ha ez a String végén szerepel: \\” ? Ez sem gond, mert ezt nem egy kivételes idézőjelnek \” fogja tekinteni, hanem az első \ jel teszi kivétellé a második \ jelet, így az idézőjel normál módon a String literál végét jelenti.

String metódusok

Lássuk akkor, hogy mit kezdhetünk a Stringekkel. Amikor egy String típusú változót használunk, valójában egy objektummal dolgozunk. A változó csak az objektumra mutat. Az objektumoknak, mint a már említett Osztályok és objektumok témakörből megtudhattad változói és metódusai vannak. A Stringek változóiról nem kell tudnod, de a metódusairól, mellyel magát a Stringet kezelheted, annál többet! Lássuk akkor ezeket példákon keresztül, hogy mire is használhatók. A felsorolás nem lesz teljes, de a legfontosabbakat úgy gondolom, hogy tartalmazza.

Stringek egyenlőségének vizsgálata – equals()

A Stringek objektumok, és két objektum csak akkor egyenlő, ha az valójában ugyanaz az objektum.

Objektumok között az == operátorral végzett egyenlőség vizsgálat nem használható!

Itt egy példa, ami ennek látszólag ellentmond. Az s1 és s2 Stringek ugyanazt az értéket kapják meg kezdőértékként, és az == működik. Itt nagy valószínűséggel a háttérben a Java fordítóprogram csal egy kicsit, látva azt, hogy a két String egyforma, ezért valószínűleg ugyanazt az objektumot rendeli hozzá mindkettőhöz:

String s1 = "abcd";
String s2 = "abcd";

System.out.println(s1 == s2); // true (???)

Rögtön kibukik azonban a következő példánál az, hogy miért is emeltem ki azt, hogy == operátorral nem hasonlítunk össze objektumokat. Nézzük a következő példát:

String s1 = "abcd";
String s2 = new String("abcd");

System.out.println(s1 == s2); // false (!!)

Itt már valóban különbözik egymástól a két String. De akkor hogyan nézhetjük meg, hogy a két String egyenlő-e, ha az objektumok nem azok? Két Stringet akkor tekintünk egyenlőnek, ha ugyanaz a tartalmuk, vagyis ugyanazt a karakterláncot tartalmazzák. Ezt az összehasonlítást egy metódussal oldották meg.

String s1 = "abcd";
String s2 = new String("abcd");

System.out.println( s1.equals(s2) ); // true

Az equals() metódust egy String objektumban (formailag az objektum címét tároló változóban) kell meghívni, és oda kell adni neki azt a másik Stringet, aminek a tartalmát szeretnénk a sajátjával összehasonlítani. A feladat szempontjából teljesen mindegy, hogy melyiket hasonlítjuk melyikhez, az s1.equals(s2) helyett az s2.equals(s1) is használható.

Stringek összefűzése – concat()

Előfordulhat, hogy egy Stringet bővítenünk kell. Hozzá akarunk fűzni valamit. Emlékszel, azt mondtam, hogy a String megváltoztathatatlan. Amikor bővítjük, akkor egy újat hozunk létre, melynek a hivatkozását átállítjuk az eredeti változóban.

Mégis rendelkezésre áll egy metódus, concat() néven, mellyel Stringeket lehet összefűzni. Még egyszer hangsúlyozom, csak Stringeket.

String s = "Indul";
s = s.concat(" a");
s = s.concat(" gorog");
s = s.concat(" aludni");
System.out.println(s);

Amennyiben nem csak Stringeket szeretnénk összefűzni, minden további nélkül használhatjuk a + operátort. Ez a nem String változókat String változóra konvertálva végzi el az összefűzést. Ez az operátor, azonban lassabb, mint a concat() metódus, ezért ha több összefűzésről van szó és csak String típusúakat szeretnél összefűzni, akkor érdemesebb a concat()-ot használni.

A sebesség mérések alapján egyébként a concat() metódus úgynevezett StringBuilder-t használ a háttérben, vagyis a fordító trükköket vet be a sebesség és memóriakímélés érdekében, és ezeket a felhasználó tudta nélkül oldja meg.

Stringek hossza – length()

Bármely String méretét (hosszát) megkaphatjuk, ha meghívjuk a length() metódusát:

s.length()

String adott karaktere – charAt()

Egy adott String bármelyik karakterét megkaphatjuk a charAt(i) metódussal, ahova az i helyére írjuk be, hogy hányadik karaktert szeretnénk megkapni. A karakterek indexelése a tömbökhöz hasonlóan 0-val kezdődik. Fontos, hogy ez egy karakter típust ad vissza! Bármely String első karaktere az s.charAt(0), az utolsó pedig az s.charAt( s.length()-1 )

s.charAt(3) // a 4. karakter (3-as index!)
s.charAt(0) // első karakter (üres Stringre indexelési hiba!)
s.charAt( s.length()-1 ) // utolsó karakter

Stringek összehasonlítása rendezés miatt – compareTo()

A Stringek összehasonlításán már túl vagyunk, de van egy másik típus is, amely fontos, ez pedig a betűrend.

Két String összehasonlítása rendezési szempontból a compareTo() metódussal történik. Ezt hasonlóan az equals() metódushoz mindkét Stringre meg lehet hívni a másikat odaadva paraméterként, de itt már nem mindegy a sorrend! A compareTo() egy számot ad vissza eredményül. Ha a szám pozitív, akkor az a String amelyikre meghívtuk a metódust a paraméterben megadott String mögött található az abc rendnek megfelelően. Ha a szám negatív, akkor előtte. 0 esetén a két String tartalma egyforma. Ezt a metódust használhatjuk akkor, ha az a feladat, hogy Stringeket rendezzünk sorba.

Az összehasonlítás megkülönbözteti a kis és nagybetűket!

String s1 = "Geza";
String s2 = "Bela";
System.out.println( s1.compareTo(s2) ); // 5
/* Az eredmény pozitív, ez azt jelenti, hogy az s1 String (amire a
 * metódust meghívtuk) a paraméterben szereplő s2 Stringhez képest
 * hátrébb található rendezési szempontból. Maga az 5-ös érték azt
 * jelenti, hogy annál a pontnál, ahol a két String különbözik
 * a két összehasonlított karakter távolsága 5 (B-G)
 */

String s3 = "Geza";
String s4 = "bela";
System.out.println( s3.compareTo(s4) ); // -27
/* Az eredmény negatív, ez azt jelenti, hogy az s3 Stringhez képest
 * az s4 String hátrébb(!) található. Ez azért van, mert a kódtáblában
 * a nagybetűk megelőzik a kisbetűket, és a compareTo() figyelembe
 * veszi ezt. Ez kiküszöbölhető a következő metódussal:
 */

System.out.println( s3.compareToIgnoreCase(s4) ); // 5
/* a compareToIgnoreCase() metódus úgy hasonlítja össze a Stringeket,
 * hogy figyelmen kívül hagyja a kis és nagybetűk közötti különbségeket.
 */

Stringek kis-nagybetűs átalakítása – toLowerCase() és toUpperCase()

A Stringeket egyszerűen átalakíthatunk csupa nagybetűssé, vagy kisbetűssé. Erre szolgálnak az s.toUpperCase() és s.toLowerCase() metódusok.

String nev = "Miko Csaba";
System.out.println( nev.toUpperCase() ); // "MIKO CSABA"
System.out.println( nev.toLowerCase() ); // "miko csaba"

Keresés Stringben – indexOf(), lastIndexOf()

Egyszerűen kereshetünk a Stringekben. Kíváncsiak vagyunk, hogy egy karakter vagy szövegrészlet megtalálható-e benne, sőt arra is, hogy hol található. Erre szolgál az s.indexOf() metódus.

String s = "abrakadabra";
System.out.println( s.indexOf("rak") ); // 2
//  A 2. indexű (3. karakternél) található a rak szócska.

System.out.println( s.indexOf("br") ); // 1
/* Az 1. indexű (2. karakternél) található a br rész
 * Fontos, hogy az indexOf() mindig az első találat helyét adja meg!
 */

System.out.println( s.indexOf("Br") ); // -1
/* Egy nem létező indexet adott eredményül, vagyis a keresett
 * részlet nem található meg a Stringben.
 */

System.out.println( s.lastIndexOf("br") ); // 8
/* A 8. indexű (9. karakternél) található a br rész, de most a
 * keresést hátulról kezdte, és onnan adja vissza az első találatot!
 */

Az indexOf() és lastIndexOf() metódusok alaphelyzetben mindig a String elejéről/végéről kezdik a keresést, de meg lehet adni nekik, hogy adott karaktertől kezdjék: indexOf(mit, honnan) Ehhez kapcsolódó feladat lehet, hogy adjuk meg, hol található a második ‘r’ betű a szóban:

String s= "abrakadabra";
int elso = s.indexOf("r");

System.out.println( s.indexOf("r", elso+1 ) );
/* Először megkeressük az első 'r' betűt, majd amikor a másodikat
 * akarjuk megkeresni, akkor megadjuk, hogy az első utáni pozíciótól
 * induljunk. Ezt a két lépést akár össze is vonhatjuk:
 */
System.out.println( s.indexOf("r", s.indexOf("r")+1 ) );

System.out.println( s.lastIndexOf("br", s.lastIndexOf("br")-1 ) );
/* Ha ugyanezt hátulról végezzük, akkor figyelni kell arra, hogy
 * az első találat előtt kell folytatni, vagyis itt -1
 * kell az első találat helyéhez képest, mivel visszafelé keresünk
 */

String kezdete és vége – startsWith(), endsWith()

Egyszerűen megvizsgálhatjuk, hogy a String egy adott karaktersorozattal kezdődik vagy végződik. Erre szolgálnak a startsWith() és endsWith() metódusok. Ezek is kis-nagybetű érzékenyek, vagyis megkülönböztetik őket.

String s = "abrakadabra";
System.out.println( s.startsWith("ab") ); // true
System.out.println( s.endsWith("ab") ); // false
System.out.println( s.startsWith("Ab") ); // false(!)

Hogy vehetem figyelmen kívül a kis-nagybetű különbséget? Nincs startsWithIgnoreCase() metódus. A trükk annyi, hogy a String kisbetűs verzióját kell összehasonlítani a keresett kezdőrésszel.

String s = "Abrakadabra";
System.out.println( s.startsWith("ab") ); // false, nem meglepő
System.out.println( s.toLowerCase().startsWith("ab") ); // true!

String karaktereinek cseréje – replace(), replaceFirst()

Egy Stringben kicserélhetünk karaktereket. Erre szolgál a replace() metódus. Ezzel egy tetszőleges karakter minden előfordulását kicseréljük egy másikra. Az is előfordulhat, hogy csak az elsőt kell kicserélni, erre szolgál a replaceFirst().

String s = "abrakadabra";
System.out.println( s.replace("a","A") ); // AbrAkAdAbrA
System.out.println( s.replace("z","A") ); // abrakadabra
// Nem volt mit cserélni, maradt az eredeti.

System.out.println( s.replaceFirst("a","A") ); // Abrakadabra
// Kicserélte az elsőt, ahogy vártuk.

s = "Abrakadabra";
System.out.println( s.replaceFirst("a","A") ); // AbrAkadabra(??)
/* Láthatod, hogy az eredeti szó már nagybetűvel kezdődött. Ekkor az
 * első betű, amit cserélni tudott nyilván a második 'a' betű lesz,
 * de itt sem felejtetted el: kis-nagybetű érzékeny metódus!
 */

String részének kinyerése – substring()

Előfordulhat, hogy egy Stringből ki kell szednünk egy kisebb részletet. Erre szolgál a substring() metódus.

Amikor egy részt akarunk kinyerni egy Stringből, akkor meg kell mondanunk, hogy milyen karakter határokhoz (indexek) viszonyítva akarom ezt megkapni. Melyiktől kezdjük, és melyik előtt fejezzük be. Ha csak a kezdő pozíciót adjuk meg, akkor onnantól a String végéig az egészet megkapjuk. A substring() mindig String típusú eredményt ad vissza.

String s = "abrakadabra";
System.out.println( s.substring(0,5) ); // abrak
System.out.println( s.substring(2,5) ); // rak
System.out.println( s.substring(5,8) ); // ada
System.out.println( s.substring(6) );   // dabra
System.out.println( s.substring(s.length()) ); // mindig üres String

A String tartalmazza-e? – contains()

Megtudhatjuk, hogy a String tartalmaz-e egy keresett részt a contains() metódus segítségével. Ez minden esetben logikai eredményt ad. True ha benne van, false ha nincs. Az utolsó trükk meg már ismerős.

String s = "Abrakadabra";
System.out.println( s.contains("rak") ); // true
System.out.println( s.contains("Rak") ); // false
System.out.println( s.contains("abra") ); // true (a vegen van!)
System.out.println( s.contains("abrak") ); // false
System.out.println( s.toLowerCase().contains("abrak") ); // true(!)

Egyébként a contains() kiváltható akár egy indexOf() metódussal is, annyi a különbség, hogy az önmagában nem logikai eredményt ad:

String s = "Abrakadabra";
System.out.println( s.indexOf("rak") > -1 ); // true
System.out.println( s.indexOf("Rak") > -1 ); // false

String szétdarabolása – split()

Több feladat esetén előfordulhat, hogy egy Stringet azért kell darabokra szedni, mert valamilyen elválasztó karakterekkel határolva több adatot tartalmaznak. Erre a darabolásra szolgál a split() metódus. A split() minden esetben egy String tömböt ad eredményül, melynek elemei a megadott karakternél széttört String darabjai lesznek. Láthatod majd a példákból, hogy csak meg kell adni a split() metódusnak, milyen karakter mentén törje szét a Stringet. Az eredmény azonnal eltárolható egy String tömbben.

Az utolsó példa kicsit furcsa. Ne lepjen meg, hogy van benne egy üres String. Mivel a String elején volt egy töréspont, ezért a bevezető ‘a’ betűnél is eltöri a Stringet, és az előtte lévő semmit is eltárolja egy üres String darabként. Ha a töréspont a String végén található, akkor azt nem veszi figyelembe, és nincs nyoma az eredménytömbben sem. Alaphelyzetben a String végén elhelyezkedő töréspontokat a split() figyelmen kívül hagyja. Legalábbis ez a verziója.

String nevsor = "Geza Eva Pal";
String[] nevek = nevsor.split(" "); // { "Geza", "Eva", "Pal" }

String nevsor2 = "Geza,Eva,Pal";
String[] nevek2 = nevsor2.split(","); // { "Geza", "Eva", "Pal" }

String s = "abrakadabra";
String[] tomb = s.split("a"); // { "", "br", "k", "d", "br" }

Nem csak egy karakter adható meg töréspontként, akár karaktersorozatot is használhatsz. Itt is igaz az, hogy elől lévő töréspont miatt üres Stringgel kezdődik az eredménytömb, a végén lévővel itt sem foglalkozna, ha lenne 🙂

String s = "abrakadabra";
String[] tomb = s.split("ab"); // { "", "rakad", "ra" }

A split() metódus másik formája két paramétert vár. Itt egy limitet lehet megadni, hogy hány elemű eredménytömböt kapjak. A metódus a következő:

s.split(töréspont,n);

Itt többféle eredmény is lehet. Az n-nel jelölt szám értéke többféle lehet, ennek megfelelő a végeredmény is.

  1. Ha n > 0,akkor n valójában azt jelenti, hogy hány darabra törje a Stringet. (vagyis n-1 esetben töri). Ha a kívánt darabok száma több, mint amennyi lehetséges, akkor a lehetséges maximumot kapjuk. Az “abrakadabra” szót nem törhetem az ‘a’ betűknél 100 részre. Mivel összesen 5 ‘a’ betű van benne, de ebből egy a végén, így maximum 6 darabra törhető. És ha az előző szónál 3 a limit? Akkor kétszer töri el a szót az elejétől kezdve, és 3 darabunk lesz. Az utolsó darabban viszont benne marad az összes olyan töréspont, ameddig a limit miatt nem jutott el.
  2. Ha n == 0, az gyakorlatilag az alap split() metódus eredményét hozza. Vagyis, a String elején lévő töréspontokat figyeli, a végén lévőket nem, és annyi darabra töri, amennyire ennek megfelelően lehetséges.
  3. Ha n < 0, akkor annyi darabra töri, amennyire csak tudja n értékétől függetlenül. És itt figyelembe veszi a String végén lévő töréspontokat is! Ilyenkor a darabok és a töréspontok ismeretében bármikor helyreállítható az eredeti String!
String s = "abrakadabra";
String[] tomb;
// n > 0
tomb = s.split("a", 1); // { "abrakadabra" } 1 darab
tomb = s.split("a", 3); // { "", "br", "kadabra" } 3 darab
tomb = s.split("a", 5); // { "", "br", "k", "d", "bra" } 5 darab
tomb = s.split("a", 8); // { "", "br", "k", "d", "br", "" } 6 darab,
                        // de nem 8, mert nincs annyi töréspont!

// n == 0
tomb = s.split("a", 0); // { "", "br", "k", "d", "br" } mint split("a")

// n < 0
tomb = s.split("a", -1); // { "", "br", "k", "d", "br", "" } hátsók is!

Speciális határolók

Vannak olyan speciális karakterek, melyeket nem lehet csak úgy odaadni a split-nek. Nem tudom, hogy a lista teljes-e, de ha valamelyik határoló esetén a split nem jó eredményt ad, érdemes majd az alább ismertetett módon megpróbálni.

String s = "abra.kad.abra";
String[] tomb;
tomb = s.split("."); // hibás!
tomb = s.split("\\."); // { "abra", "kad", "abra" }

s = "abra|kad|abra";
tomb = s.split("|"); // hibás!
tomb = s.split("\\|"); // { "abra", "kad", "abra" }

s = "abra\\kad\\abra"; // már a megadáskor ügyelni kell a \ jelre!
tomb = s.split("\"); // hibás!
tomb = s.split("\\"); // hibás!!!
tomb = s.split("\\\\"); // { "abra", "kad", "abra" }

Az utolsó példa esetleg kis magyarázatot igényel. Itt határoló karakternek szeretnénk megadni a \ jelet. A splitnek ha \\ módon adjuk meg a határolókat, azt sem dolgozza fel, mert ő ezt egy \ jelnek veszi. Itt a helyes megoldás a \\\\, amiből literálként \\ marad, és ő ezt dolgozza fel \ jelként. Ha egy fájlból beolvasott Stringben vannak ilyen jelek, akkor nem kell kivételként megadni, tehát a fájlban elég, ha így szerepel:

abra\kad\abra

Literálként viszont a \ jel önmagában nem adható meg, így Stringként megadva ebből ez lesz:

s = "abra\\kad\\abra";

Csak zárójelben jegyzem meg, hogy a split()-nek megadandó töréspont nem csak String lehet, hanem egy úgynevezett reguláris kifejezés is. Ez egy nagyon jól paraméterezhető illesztési minta, amivel teljesen átláthatóvá tudunk tenni összetett mintákat is.

Több határoló együttes használata

Előfordulhat olyan feladat, amelynél egy adott Stringet úgy kell több darabra törni, hogy nem csak egyféle határolót használunk. Nyilván meg lehetne oldani az eddig leírtak alapján is, de az meglehetősen körülményes lenne. Tegyük fel adott egy String, ami így néz ki:

String s = "123a4a56b78b9a0";

 

Ebben a sorban olyan Stringet látunk, ahol az egyes darabokat (a leendő sázmokat) betűk választják el egymástól. A helyzet azonban az, hogy nem csak egyfajta betű jelenik meg határolóként. Split-nél eddig azt tanultuk, hogy meg kell adni azt a határolót, aminél szét akarjuk törni a Stringet. A határoló állhat több karakterből is, de ez akkor is csak egyetlen darab lesz. Lássuk hogy lehet megoldani azt, hogy a fenti String-et a betűknél tördelve megkapjuk a benne lévő számokat:

String s = "123a4a56b78b9a0";
String[] darabok = s.split("a|b|c");

for( int i = 0; i < darabok.length; i++ )
{
  System.out.println(darabok[i]);
}

Ha lefuttatod a fenti kódot, akkor láthatod, hogy valóban az összes számot megkaptuk, és egyetlen betűt sem találunk a darabokban. Gyakorlatilag annyi a teendőnk, hogy egy | jellel elválasztottuk egymástól a határolókat egy felsorolásban. Ez a | jel valójában egy vagy műveletnek, de ez nem a logikai vagy, ne keverjük vele, csak egyetlen jelből áll. Ha tehát több határolónál kell egy Stringet darabolnunk, akkor használjuk bátran. Egy jó példa erre az emelt informatika érettéségi feladatok fehérje nevű feladata (2006 május).

Stringet karakterekre bontása – toCharArray()

Előfordulhat, hogy egy Stringet szét kell bontani karaktereire.

String s = "hokusz";
char[] tomb = s.toCharArray(); // { 'h', 'o', 'k', 'u', 's', 'z' }

String feladatok

Akkor kombináljuk az eddig tanultakat, nézzük meg a metódusok használatát komplexebb feladatok esetén.

Írjuk ki a nevünket vízszintesen kicsit széthúzva (tegyünk a nevünk betűi közé plusz szóközöket):

String nev = "Miko Csaba";
for (int i = 0; i < nev.length(); i++)
{
  System.out.print(nev.charAt(i)+" ");
}

Adjuk meg a nevünket, írjuk ki egy oszlopba:

String nev = "Miko Csaba";
for( int i = 0; i < nev.length(); i++ )
{
  System.out.println( nev.charAt(i) );
}

Számoljuk meg, hány a betű található a nevünkben:

String nev = "Miko Csaba";
int adb = 0;
for( int i = 0; i < nev.length(); i++ )
{
  if( nev.charAt(i) == 'a' )
  {
    adb++;
  }
}
System.out.println( "A nevben "+adb+" darab 'a' betu talalhato." );

Írjuk ki, hányszor szerepel a mondatban ‘a’ névelő. Kis és nagybetűs változat is számít!

String nev = "A Java tanulasa nem egyszeru feladat, "+
             "de a szorgalom meghozza gyumolcset.";
String[] tomb = nev.toLowerCase().split(" ");
int adb = 0;
for( int i = 0; i < tomb.length; i++ )
{
  if( tomb[i].equals("a") )
  {
    adb++;
  }
}
System.out.println( "A nevben "+adb+" darab 'a' nevelo talalhato." );

Következő lecke: Alap algoritmusok

9 Replies to “Java programozás 15. – String”

  1. Pingback: Java programozás feladat – Kézilabda |

  2. Pingback: Java programozás 19. – StringBuilder |

  3. Pingback: Java programozás 21. – Fájlkezelés alapjai

  4. Pingback: Java programozás 14. – Tömbök

  5. Kedves Tanár Úr!
    Nagyon szeretem az anyagait, mert könnyen érthetőek, követhetőek. Köszönet értük!!! 🙂
    A mostani leckében viszont az alábbi részt nem tudtam követni. Nem az s3 String van előrébb az s4-hez képest?

    Köszönöm szépen
    Üdvözlettel:
    Nagy Katalin

    String s3 = “Geza”;
    String s4 = “bela”;
    System.out.println( s3.compareTo(s4) ); // -27
    /* Az eredmény negatív, ez azt jelenti, hogy az s3 Stringhez képest
    * az s4 String előrébb(!) található.

    • Igaza van, javítottam a hibát. Helyesen:
      String s3 = “Geza”;
      String s4 = “bela”;
      System.out.println( s3.compareTo(s4) ); // -27
      /* Az eredmény negatív, ez azt jelenti, hogy az s3 Stringhez képest
      * az s4 String hátrébb(!) található.

      Köszönöm az észrevételt, és további jó tanulást! 🙂

  6. Köszönöm szépen a gyors választ. 🙂 Ha nem zavarom vele, lenne egy kérdésem.
    A .split() metódus nem teljesen világos számomra.
    String s = “abrakadabra”;
    String[] tomb;
    // n > 0
    tomb = s.split(“a”, 5); // { “”, “br”, “k”, “d”, “bra” } 5 darab
    tomb = s.split(“a”, 8); // { “”, “br”, “k”, “d”, “br”, “” } akkor is 5! // Itt látszólag 6 elem van az eredménytömbben, és a magyarázatban is azt írja, hogy maximum 6 részre törhető aszó az “a” karakter mentén.
    Ugyanakkor előtte szó van arról, hogy ha a töréspont a String végén található, akkor annak nincs nyoma az eredménytömbben.
    Úgy kell érteni a fenti példát, hogy 6 elemre törte a szót, de mivel az utolsó a String végén található, azt egyszerűen nem veszi figyelembe?
    Előre is köszönöm szépen
    Üdvözlettel:
    Nagy Katalin

    • Látszik, hogy nagyon aprólékosan átolvassa a dolgokat 🙂

      Valóban igaza van, hibás volt ez a rész. Ha 8 darabra szeretném törni, akkor annyi töréspontot dolgoz fel, amennyiből a 8 darab létrejöhet. Ha lenne 10 ‘a’ betű, akkor ebből 7-nél széttörné a Stringet, a többit békén hagyná. Mivel itt azonban 5 darab ‘a’ betű van, így maximum 6 darab jöhet létre, ezért mindet feldolgozza, a végén lévőt is beleértve. Itt gyakorlatilag ugyanazt az eredményt kapjuk, mintha s.split(“a”, -1) módon dolgoznánk fel.

      A lecke elejére beraktam egy új pontot, Speciális String literálok címmel, valamint a splitnél kimaradt egy rész, azt gyorsan bele is írtam, valamint. Ez a két dolog kapcsolódik egymáshoz.

      További jó olvasgatást, és várom a hibákat 🙂

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük

*

Ez a weboldal az Akismet szolgáltatását használja a spam kiszűrésére. Tudjunk meg többet arról, hogyan dolgozzák fel a hozzászólásunk adatait..