Liigu peamise sisu juurde

Sümbolid ja sõned

Sissejuhatus

Javas on kaks andmetüüpi, mis võimaldavad tegeleda tekstiliste andmetega - char ja String. Teisisõnu sümbolid ja sõned.
char on primitiivne tüüp, mis esindab ühte unicode sümbolit. String omakorda on viitetüüp, mis esindab sümbolite jada.
Kuna tekstil põhinevad andmed on tihedalt kasutusel, on oluline mõista nende kahe tüübi erinevusi ja võimalusi.

char tüüp - sümbolid

char on primitiivne andmetüüp, mis esindab ühte 16-bitist unicode sümbolit (tähti, numbreid, kirjavahemärke, erisümboleid jne).

Sümbolite väärtustamine

Üksikuid sümboleid saab luua järgnevalt (kasutades ülakomasid - ')

char letter = 'A';
char digit = '9';
char symbol = '$';
char space = ' ';
oht

Üksikud sümbolid on alati märgitud ülakomade (') vahele, mitte jutumärkide (") vahele. Jutumärgid on mõeldud sõnede jaoks.

Samuti on tähtis et char saab maksimaalselt sisaldada ainult ühte tähemärki. Vastasel juhul tekib kompileerimisviga:

char a = 'a';   // Correct
char b = 'b '; // b + whitespace -> Error - java: unclosed character literal

Sümboleid saab ka esitada nende unicode väärtuste kaudu:

char letterA = 65;           // ASCII value for 'A'
char euroSign = '\u20AC'; // Unicode escape value for '€'
char heart = '\u2764'; // Unicode escape value for '❤'

Toimingud sümbolitel

Sümbolite peal on võimalik läbi viia järgnevaid tegevusi:

// Character declaration
char a = 'A';
char b = 'B';

// Character comparisson, compares unicode value
boolean result = (a < b); // true (65 < 66)

// Arithmetic calculations
char nextChar = (char)(a + 1); // 'B' -> A + 1 = B
int difference = b - a; // 1

// Character class has some useful helper methods
Character.isDigit('5'); // true
Character.isLetter('A'); // true
Character.isUpperCase('A'); // true
Character.isLowerCase('a'); // true
Character.isWhitespace(' '); // true

// Character conversion
char upper = Character.toUpperCase('a'); // 'A'
char lower = Character.toLowerCase('A'); // 'a'

String klass - sõned

Sõned (ingl.k. string) on objektid, mis kuuluvad klassi java.lang.String. Sõne on sümbolite kogum. Sõnest võib mõelda kui tähtede (või üldisemalt sümbolite) massiivist. Sõne on Java keeles objekt ehk ta on olemuselt viitetüüp. Javas sõne jaoks primitiivi ei ole olemas. See tähendab, et tema kohta kehtivad natuke teised reeglid kui primitiivsete andmetüüpide puhul.

Sõnede väärtustamine

Sõne-tüüpi muutujat saab luua järgnevalt:

String greeting = "Hello, world!";
String empty = "";

Esimese näite puhul luuakse sõne, mille väärtus on "Hello world!", teise näite puhul tõhi sõne.

Kuna sõned on objektid, siis lisaks tekstilisele väärtusele võib väärtuseks olla ka null või olla üldse initsialiseerimata:

String s1 = null;

String s2;
hoiatus

Tuletage muutujate peatükist meelde, kuidas antud juhul deklaleerimine ja initsialiseermine töötab.
Millisel juhul alumine koodirida ei tööta ja lõppeb kompileerimisveaga?

Sõnede võrdlemine

Sõnede puhul ei saa kasutada == võrdlust. See võrdleb objektide puhul seda, kas nad on täpselt sama instants. Sõnede puhul oleks pigem vaja kontrollida nende sisu ning selle saavutamiseks kasutatakse .equals() või .equalsIgnoreCase() meetodit:

String s1 = new String("aaa");
String s2 = new String("aaa");
String s3 = "AaA";

// Wrong
boolean isEqualWrong = s1 == s2; // false - they are not the same instance

// Correct
boolean isEqualCorrect = s1.equals(s2); // true - same contents

// Case-insensitive equality control
boolean isEqualIgnoreCase = s1.equalsIgnoreCase(s3); // true - same contents if case-sensitivity is ignored

Leksikograafiliseks (sõnede tähestikuline järjekord) võrdlemiseks kasutatakse .compareTo() ja .compareToIgnoreCase() meetodeid

String s1 = "Aaa";
String s2 = "Aaa";
String s3 = "aaa";

int compare1 = s1.compareTo(s2); // 0 (equal)
int compare2 = s1.compareTo(s3); // negative (s1 < s3)
int compare3 = s1.compareToIgnoreCase(s3); // 0

Sõnede muutmine

Sõned on Javas muutumatud ehk nende sisu ei saa muuta.
Näiteks:

String s1 = "Apple";
s1 = "Orange";

Sellisel juhul ei muudeta sõne s1 sisu. Esimene rida loob objekti, mille sisuks on "Apple" ja omistab selle viida s1'le. Teine rida loob uue objekti, mille sisuks on "Orange" ja omistab selle viida s1'le.

Kui nüüd teha näiteks

s1 += " juice";

Selle asemel, et "Orange" muutuks, luuakse täiesti uus sõne objekt sisuga "Orange juice", millel on uus viit.

Sõnede liitmine

Sõnesid saab liita kasutades liitmismärki +. See loob uue sõne, mis koosneb esimesest ja teisest sõnest järjestikku.

String firstName = "Ago";
String lastName = "Luberg";
String fullName = firstName + " " + lastName; // "Ago Luberg"

Sõnede liitmist saab teha ka otse System.out.println käsus või koos muude andmetega. Samuti on võimalik sõne koostada mitmest erinevast osast:

// Combination with other types
int age = 25;
System.out.println("I am " + age + " years old"); // prints "I am 25 years old"
oht

+ või += kasutamine tsükklites sõnede loomiseks on ebaefektiivne ning seda tuleks vältida. Põhjuseks on see, et igal uuel tsüklil luuakse uus sõne objekt. Täpsem põhjendus koos näite ja lahendusega on välja toodud siin.

Levinumad meetodid

Järgnevalt on välja toodud mõned kasulikud abimeetodid, mis String klassis esinevad.

Sõne pikkus ja indeksil asuv sümbol

String text = "Tere";

// String length
int len = text.length(); // 4

// Returns symbol at specified index
char first = text.charAt(0); // 'T'
char last = text.charAt(3); // 'e'

// Transform String into array of characters.
// Useful for analyzing string character by character
char[] chars = text.toCharArray(); // ['T', 'e', 'r', 'e']
hoiatus

charAt puhul on tähtis arvestada, et kui ette antud indeks on suurem kui sõne pikkus, siis tõstatakse IndexOutOfBoundsException erind.

Alamsõned (substring)

.substring meetod tagastab ette antud sõnest alamsõne, mis jääb tähistatud indeksite vahele:

String text = "Tere maailm"; // Indexes range from 0-10

// Returns substring from starting index till the end
String sub1 = text.substring(5); // "maailm"

// Start and stop index (stop is non-inclusive)
String sub2 = text.substring(0, 4); // "Tere"
String sub3 = text.substring(5, 11); // "maailm"
hoiatus

substring puhul on tähtis arvestada, et kui algus- või lõppindeks on suuremad kui sõne pikkus, siis tõstatakse IndexOutOfBoundsException erind.

Sõnest otsimine

String text = "Tere maailm";

// Check if String contains specified substring
boolean contains = text.contains("maailm"); // true

// Find index of substring
int index1 = text.indexOf("e"); // 1 (defaults to first occurence)
int index2 = text.indexOf("e", 2); // 3 (can specify from what index onwards to start search)
int index3 = text.indexOf("xyz"); // -1 (returns -1 if not found)

// Find last occurence of a substring
int lastIndex = text.lastIndexOf("e"); // 3

// Check if text starts or ends with specified substring
boolean starts = text.startsWith("Tere"); // true
boolean ends = text.endsWith("maailm"); // true

Teisendamine ja muundamine

Meetodid mis muudavad sõne läbivalt suurteks või väikesteks tähtedeks:

String text = "Tere Maailm";

String upper = text.toUpperCase(); // "TERE MAAILM"
String lower = text.toLowerCase(); // "tere maailm"

Üleliigseid tühikuid sõne algusest ja lõpust on võimalik järgnevalt eemaldada:

String text = "  Tere maailm  ";

String trimmed = text.trim(); // "Tere maailm"

isEmpty, isBlank

.isEmpty() kontrollib, kas tegemist on tühisõnega ehk "". See meetod ei ole võimeline tuvastama, kas sõne koosneb ainult tühikutest (ehk on sisuliselt tühisõne). Selle jaoks on alates Java versioon 11-st võimalik kasutada .isBlank() meetodit:

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

boolean empty = s1.isEmpty(); // true
boolean s2Empty = s2.isEmpty(); // false

boolean blank = s1.isBlank(); // true
boolean s2blank = s2.isBlank(); // true

Asendamine

String text = "Tere maailm";

// Replaces a single symbol
String replaced1 = text.replace('e', 'a'); // "Tara maailm"

// Replaces a whole substring
String replaced2 = text.replace("maailm", "Java"); // "Tere Java"

// replaceAll accepts regex patterns as well
// Replaces all occurences which match the pattern
String replaced3 = text.replaceAll("\\s", "_"); // "Tere_maailm"

// Replaces the first occurence, also accepts regex patterns
String replaced4 = text.replaceFirst("e", "E"); // "TerE maailm"

Sõnede tükeldamine

String text = "apple,banana,cherry";

String[] fruits = text.split(","); // ["apple", "banana", "cherry"]

// Second parameter limits how many splits to do
String text2 = "a:b:c:d";
String[] parts = text2.split(":", 2); // ["a", "b:c:d"]

// Split also accepts regex patterns
// Split by comma, semicolon, or one/more whitespace characters
String text3 = "apple,banana;orange grape";
String[] parts2 = text3.split("[,;\\s]+"); // ["apple", "banana", "orange", "grape"]

Vormindamine

Javas on sõne klassis olemas staatiline avalik meetod format, mis võimaldab konverteerida sisendit soovitud sõne kujule.

Üldine süntaks: %[argumendiIndeks$][lipud][laius][.täpsus]konverteerimiseKarakter ([] sees pole kohustuslikud)

String formatted = String.format("Name: %s, Age: %d", "Juhan", 25);
// "Name: Juhan, Age: 25"

// Some of the possible placeholders
String.format("%d", 145); // "145" (integer)
String.format("%f", 11.6455555); // "11.645556" (float)
String.format("%.2f", 11.6455555); // "11.65" (delimiter limit)
String.format("%s", "tere"); // "tere" (string)
String.format("%c", 'A'); // "A" (character)
String.format("%b", true); // "true" (boolean)
String.format("%x", 255); // "ff" (hexadecimal value)

// Width, allignment and fill
String.format("%5d", 42); // " 42" (width of 5)
String.format("%-5d", 42); // "42 " (alligned to the left)
String.format("%05d", 42); // "00042" (Fill with zeroes)

// Also possible to define input argument placement
// %2$s - (%2) second argument, ($s) type string
String.format("%2$s %1$s", "maailm", "Tere"); // "Tere maailm"

null-väärtuse käsitlemine

Objektide (ka sõne) puhul on null eriline "väärtus". Sisuliselt tähendab see seda, et väärtus on määramata. Kui muidu objekti andmetüüp viitab lihtsustatult mäluaadressile, kus objekti sisu/väärtus salvestatud, siis null tähendab seda, et mälus pole selle objekti kohta (veel) andmeid. null "väärtusega" objekti puhul ei saa ühtegi meetodit kasutada. Ehk siis määramata sõne puhul s.length(); tuleks viga NullPointerException. Kuna s on null, siis meil objekti (sõne) ennast polegi, seega, kõik pöördumised s poole annavad tulemuseks null.

Kui kirjutada selline kontroll:

if (s.equals("yes")) {
// do something if user entered "yes"
}

Juhul kui mingil põhjusel s on null, annab programm veateate. Eelnevalt tuleks kontrollida kas s on väärtustatud:

if (s == null) {
// here s is null
} else {
// here s is not null, we can use string methods
System.out.println(s.length());
}

Teine võimalus juhul kui meid huvitab, kas kaks sõne on võrdsed, saab kirjutada nii:

if ("yes".equals(s)) {
// checks if s value is "yes"
}

"yes" on eelmise näite puhul samamoodi sõne ehk objekt. Kuna see objekt ei ole null, võib seda kasutada kontrollimise puhul esimesel kohal. Kui kaks sõne on sama sisuga, siis ei ole vahet, kumba kummaga kontrollime - mõlemal juhul peaks equals meetod tagastama true. Järelikult selle näite puhul, isegi kui s on null, ei teki viga sest ei kutsuta selle muutuja kaudu meetodeid välja.