Sztringek
Az előadás videója elérhető a itt.
A sztring manipulációs tevékenységek vitathatatlanul a leggyakoribb tevékenységek a számítógépes programokban, így nagyon fontos, hogy alaposabban megismerkedjünk ezzel a típussal, illetve megvalósításával.
Karakterek sorozata¶
A String osztály megvalósítja a CharSequence interface-t, amely karakter értékek sorozatát jelképezi.
Fontos azonban, hogy minden String objektum, és nem karaktertömb.
A CharSequence interface leírása alapján minden sztringre le lehet kérni annak hosszát (int length()
), illetve adott indexen levő karakterének értékét (char charAt(int)
), és vissza lehet adni adott indexek közötti karakterek sorozatát (CharSequence subSequence(int start, int end)
).
CharSequence interface-t nemcsak a String, de a CharBuffer, Segment, StringBuffer, StringBuilder osztályok is megvalósítják, így a fenti metódusok ezeknél is értelmezettek lesznek.
Sztringek¶
Ha egy kicsit elmerengünk a String JDK dokumentációjában, akkor talán feltűnhet, hogy valamennyi művelete a Stringnek magát az eredeti objektumot nem bántja, minden esetben egy új String jön létre az aktuális módosítás eredményeként.
public class StringPelda {
public static void main(String[] args) {
String str1 = "abc";
// ekvivalens az alábbival:
char data[] = {'a', 'b', 'c'};
String str2 = new String(data);
// további példák:
System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3); // -> "c" (2)--(3-1) karakterek
System.out.println(c);
String d = cde.substring(1,2); // -> "d" (1)--(2-1) karakterek
System.out.println(d);
}
}
Kimenet
abc
abccde
c
d
Amíg módosítani nem szeretnénk a Stringet, az teljesen úgyanúgy működik, mint egy karakter sorozat. Nagyon sok konstruktort definiáltak a String osztályhoz, de a leggyakoribban használt talán az, ami egy karakter tömb alapján hozza létre a Stringet. Mivel a String az egyik leggyakrabban használt osztály, így a nyelv az automatikus konstruktorhívás lehetőségét is felkínálja, azaz new hívás nélkül, egyszerű értékadással is inicializálható a String egy karaktersorozattal, vagy sztring konstanssal.
Azonban a Stringek annyival többek már így is a karakter sorozatoknál, hogy értelmezve van rajtuk a "+" operátor, aminek hatására két sztring összefűzhető, és eredményül keletkezik egy harmadik String. Ez a "+" operátor igen érdekes olyan értelemben, hogy a Java a String kivételével nem teszi lehetővé ennek az operátornak a felüldefiniálását.
public class Concatenation {
public static void main(String[] args) {
String def = "def";
String s = "abc" + def + "ghi" + 47;
System.out.println(s);
}
}
Kimenet
abcdefghi47
A String osztály számos metódussal próbálja könnyíteni a Stringekkel kapcsolatos műveletek elvégzését. A leggyakoribb metódusok a következők:
Metódus neve | Leírása |
---|---|
length() | visszaadja az aktuális sztring hosszát |
charAt() | visszaadja a sztring adott pozícióján levő karaktert |
getChars() | az aktuális sztring adott karakterétől adott karakteréig bemásolja a cél karaktertömb adott indexű elemétől kezdve |
toCharArray() | karaktertömbként adja vissza az aktuális sztringet |
equals(), equalsIgnoreCase() | összehasonlítja az aktuális sztringet a paraméterben kapottal; u.a. csak a kis- és nagybetűk közötti eltéréseket figyelmen kívül hagyja |
compareTo(), compareToIgnoreCase() |
összehasonlítja az aktuális sztringgel a paraméterben kapott sztringet lexikografikusan; u.a, mint az előző, csak a kis- és nagybetűk közötti eltérést nem veszi figyelembe |
contains() | visszatér true-val, ha a paraméterben kapott karakter sorozatot tartalmazza a sztring |
regionMatches() | összehasonlítja az aktuális és a paraméterben kapott sztringek adott régióit |
startsWith(), endsWith() | ellenőrzi, hogy az aktuális sztring a paraméterben kapott sztringgel kezdődik, vagy végződik-e |
indexOf(), lastIndexOf() | visszatér az adott sztringben hol található az első/utolsó előfordulása az adott karakternek |
substring() | visszaad egy új sztringet, ami az eredeti rész sztringje |
replace() | visszatér egy új sztringgel, amiben az aktuális sztringben levő adott karaktert lecserél egy másikra |
toLowerCase(), toUpperCase() | visszaad egy új sztringet, ami az aktuális sztring valamennyi karakterét nagybetűsíti/kisbetűsíti |
trim() | visszaad egy új sztringet, amiben levágja a String végi whitespace karaktereket |
valueOf() | az adott paramétert Stringgé konvertálja |
Sztring formázás¶
A C nyelvben megismert sztring formázás kényelmes lehet sokszor. Ez megvalósítható JAVA-ban a String osztály format metódusával, vagy azzal, hogy a PrintStream objektum printf vagy format metódusát hívjuk a kiíráskor.
public class SimpleFormat {
public static void main(String[] args) {
int x = 5;
double y = 5.332542;
// The old way:
System.out.println("Sor 1: [" + x + " " + y + "]");
// The new way:
System.out.format("Sor 1: [%d %f]\n", x, y);
// or
System.out.printf("Row 1: [%d %f]\n", x, y);
}
}
Kimenet
Sor 1: [5 5.332542]
Sor 1: [5 5.332542]
Sor 1: [5 5.332542]
StringBuilder és StringBuffer¶
Ahogy láttuk, a String osztály objektumait nem tudjuk megváltoztatni, minden esetben új sztring jön létre, ha valamilyen műveletet végzünk egy konkrét sztringen. Néha azonban előfordul, hogy ez a tulajdonság nem annyira praktikus, és valóban módosítani akarjuk az adott karaktersorozatot. A StringBuilder és StringBuffer osztályok ezt a funkcionalitást biztosítják többek között az append és insert metódusok által. Annyi különbség van köztük, hogy a StringBuilder gyorsabb, de nem szál biztos, ellentétben a StringBufferrel.
Sztringek darabolása¶
Sztringek feldolgozásakor gyakori az a feladat, hogy egy adott sztringet rész sztringekre bontsunk valamilyen szeparáló karakter mentén. (Például egy csv fájl feldolgozásakor minden sor egy-egy összetett sztring, amiben az egyes elemeket ",", vagy ";" választ el egymástól.)
A Tokenizer osztály segíthet nekünk ebben a darabolásban. A Tokenizer objektum inicializálásakor meg kell adjuk, hogy mely sztringet szeretnénk darabolni, illetve meg kell adjuk a szeparáló karaktert. Ezután a countTokens, hasMoreTokens, valamint nextToken metódusokkal el tudjuk érni a feldarabolt sztring részsztringjeit. (Hasonló megoldást kínál a String osztály split metódusa is egyébként.)
import java.util.*;
public class Tokenizer {
public static void main(String args[]) {
String mydelim = " : ";
String mystr = "JAVA : Code : String : Tokenizer : Geeks";
StringTokenizer geeks3 = new StringTokenizer(mystr, mydelim);
int count = geeks3.countTokens();
System.out.println("Number of tokens : " + count);
for (int i = 0; i <count; i++)
System.out.println("token at [" + i + "] : " + geeks3.nextToken());
while (geeks3.hasMoreTokens())
System.out.println(geeks3.nextToken());
}
}
Kimenet
Number of tokens : 5
token at [0] : JAVA
token at [1] : Code
token at [2] : String
token at [3] : Tokenizer
token at [4] : Geeks
A fenti példa egy kicsit csalfa, valójában a while itt már nem csinál semmit, mivel a nextToken() legfeljebb annyiszor hívható, amennyi darabra vágható a sztring. Ha kikommenteznénk a for ciklust, akkor viszont a while ciklus járná végig a felsorolt elemeket, és while ciklus kiírása érvényesülne.
Sztringek összefűzése¶
Ha szét tudunk darabolni egy sztringet, akkor persze hasonló módon össze is rakhatunk sztringeket, valamilyen szeparátorral elválasztva a rész sztringeket. Ezt teszi meg nekünk a StringJoiner osztály, ami ezen felül egy elő-, és utótagot is képes az összetett sztringhez illeszteni.
import java.util.StringJoiner;
class StringJoin {
public static void main(String[] args) {
StringJoiner sj = new StringJoiner(";", "prefix-", "-suffix");
sj.add("Java");
sj.add("Code");
sj.add("String");
sj.add("Joiner");
System.out.println(sj);
}
Kimenet
prefix-Java;Code;String;Joiner-suffix