Nauka programowania Java #8: String, StringBuilder, StringBuffer

Pierwszą rzecz, którą musisz wiedzieć o łańcuchach znaków to to, że nie istnieje typ prosty je obsługujący. String w Javie jest klasą, której implementacja jest oparta na typie znakowym (char) i tablicach. Obie te kwestie omawiałem już wcześnie, także powinieneś rozumieć, że String to nic innego jak zlepek charów. Teoretycznie moglibyśmy stworzyć sami tablicę charów i wypełniać je pojedyńczymi znakami, ale byłoby to niemiłosiernie uciążliwe.
String podobnie jak każda klasa opakowująca (Integer, Double, itp.) jest literałem i można przypisywać do niego wartości w dwojaki sposób: przez new i znak równości.

String someStringObject = new String(„Ala ma kota”);
String quickString = “Ala ma kota”;

Teraz spróbujmy porównaż czy dwa łancuchy zawierają tą samą zawartość. W przypadku liczb można to zrobić bardzo łatwo używając operatora porównania (==) oraz instrukcji warunkowej if. Ogólny zarys jej działania jest bardzo prosty: jeśli coś spełnia warunek to jest wykonywane, w przeciwnym razie wykonywany jest kod, który został napisany po instrukcji else.
Na przykład:

int firstNumberToCheck = 1;
int secondNumberToCheck = 2;
if (firstNumberToCheck == secondNumberToCheck) {
   System.out.println(“Są rownie”);
} else {
   System.out.println(„Nie są sobie równe);
}

 

Rezultat: nie są sobie równe (łatwe do przewidzenia). Teraz spróbuję zrobić coś podobnego z instrukcjami

Instrukcje warunkowe mogą mieć więcej niż dwa warunki.

String checkValue = "1";

if (checkValue == 1) {
  System.out.println("1");
} else if (checkValue == 2) {
  System.out.println("2");
} else {
  System.out.println("coś innego");
}

 

Teraz spróbuję porównać dwa Stringi. Wynik: „1” oznacza, że udało mi się sprawdzić czy String jest taki sam jak „1”. Ale co się stanie, gdy stworzę łańcuch poprzez słowo kluczowe ‘new’?

String stringMyObject = new String("1");
if (stringMyObject == "1") {
   System.out.println("1");
} else {
   System.out.println("coś innego");
}

 

Program nie zadziałał poprawnie. Dzieje się tak, dlatego że dla porównywania Stringów utworzonych jako obiekty należy używać specjalnej metody porównującej o nazwie ‘equals’. Sprawdźmy zatem.

String stringTwo = new String("2");
if (stringTwo.equals("2")) {
   System.out.println("2");
} else {
   System.out.println("coś innego");
}

Teraz udało się porównać dwa Stringi.

Zobaczmy co jeszcze oferuje klasa String.

  • charAt(indexNumber) – zwraca znak po indeksie z łańcucha
  • indexOf(charValue) – odwrotna metoda do poprzedniej, zwraca numer indeksu pierwszego wystąpienia danego znaku
  • length() – zwraca długość łańcucha znaków
  • contains(charValue) – zwraca ‘true’, jeśli w łańcuchu znajdował się szukany znak.
  • matches(stringValue) – podobna metoda to tej wyżej, tylko wyszukuje w łańcuchu inny tekst po wyrażeniu regularnym*.
  • contact(stringValue) – łączy ze sobą dwa łańcuchy. Alternatywnie możesz też używać operatora dodawania (+), aby osiągnąć ten sam efekt.
  • isEmpty() – zwraca ‘true’, gdy łańcuch jest pusty (ale nie może być nullem!)
  • replaceAll(originalStringToReplace, newVersionOfString) – szuka wyrażeniem regularnym określonego fragmentu tekstu i podmienia go na nowy we wszystkich miejscach.
  • split(delimiter) – dzieli tekst na części, jeśli oddziela je konkretny delimiter (np. spacja, przecinek, dwukropek, itp.)
  • substring(beginIndex, endIndex) – wydziela fragment tekstu zawartego między indeksami
  • toLowerCase() – zmienia wszystkie znaki z liter wielkich na małe
  • toUpperCase() – to samo, co wyżej tylko zamienia na wielkie
  • trim() – usuwa spacje wiodące (na początku tekstu) oraz te na końcu.

Jest oczywiście jeszcze wiele innych metod. Wymieniłem jedynie te najciekawsze.

Klasa String ma jeszcze jedną ważną właściwość, którą warto poznać, jest klasą typu „immutable” (niezmienna). Nigdy nie używam w języku potocznym określenia polskiego, więc pozwolisz, że będę w tym i następnych postach używał tylko wersji angielskiej. Idea takiej klasy jest taka, że zawartość jej raz stworzonego obiektu pozostaje cały czas taka sama. O klasach immutable jeszcze napiszę, natomiast na ten moment ważne jest zrozumienie, że stworzenie raz jakiegoś łańcucha znaków, powoduje że, gdy chcemy do niego dodać kolejny to Java może stworzyć w pamięci nowy łańcuch zamiast (co wydawałoby się logiczne) dodać do obecnego kolejny fragment. W takim wypadku, aby oszczędzać wydajniej jest używać klasy StringBuilder lub synchronizowanej wersji tej klasy o nazwie StringBuffer. Oto przykład jak można efektywnie dodawać kolejne fragmenty tekstu do siebie w pętli.

String immutableString = "Sample text.";
StringBuilder builder = new StringBuilder(immutableString);
for (int i =0; i <10; i++) {
   builder.append("\nLoop counter: " + i);
}
System.out.println(builder.toString());

 

Analogicznie możesz tak samo używać klasy StringBuffer. Jest to synchronizowana wersja StringBuildera przeznaczona do pracy w środowisku wielowątkowym.

 

*Wyrażenie regularne(regex) – jest to specjalny zapis w informatyce, który używając pewnych symboli, pozwala komputerowi wyszukać tekst zgodny z podanym wzorcem (więcej poszukaj na tej stronie: https://regexr.com).

Dodaj komentarz