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 zmiennych typu char. Teoretycznie moglibyśmy stworzyć sami tablicę tego rodzaju i wypełniać je pojedynczymi znakami, ale byłoby to niemiłosiernie uciążliwe.

String jest literałem

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 łańcuchy 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");
}

Używanie equals przy Stringach

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 łancuchy znaków.

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.

StringBuilder i StringBuffer

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).

Link do lekcji: https://github.com/developeronthego/java-basics/tree/main/src/main/java/basics/lesson8

Jeśli chcesz dowiedzieć się czegoś więcej o klasach immutable: Java zaawansowane #12: obiekty niezmienne (immutable)

Możesz również polubić…

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.