1 klasaStringTokenizer

I kilka innych typowych scenariuszy pracy z łańcuchami. Jak podzielić ciąg na wiele części? Można to zrobić na kilka sposobów.

metodasplit()

Pierwszym sposobem podzielenia łańcucha na wiele części jest użycie metody split(). Jako parametr należy przekazać do niego wyrażenie regularne: specjalny wzorzec łańcucha ogranicznika. Czym jest wyrażenie regularne, dowiesz się w zadaniu Java Multithreading .

Przykład:

Kod Wynik
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
Wynikiem będzie tablica trzech ciągów:
["Good ", "ws everyo", "!"]

Proste, ale czasami takie podejście jest zbędne. Jeśli występuje wiele separatorów, na przykład „spacja”, „enter”, „tab”, „kropka”, należy skonstruować dość złożone wyrażenie regularne. Jest trudny do odczytania, co oznacza, że ​​trudno jest wprowadzić w nim zmiany.

KlasaStringTokenizer

Java ma specjalną klasę, której całe zadanie polega na podziale łańcucha na podciągi.

Ta klasa nie używa wyrażeń regularnych; zamiast tego po prostu przekazuje ciąg składający się ze znaków separatora. Zaletą tego podejścia jest to, że nie rozbija od razu całej linii na kawałki, ale powoli przechodzi od początku do końca.

Klasa składa się z konstruktora i dwóch głównych metod. W konstruktorze należy przekazać ciąg znaków, który dzielimy na części, a łańcuch ten jest zbiorem znaków służących do podziału.

Metody Opis
String nextToken()
Zwraca następny podciąg
boolean hasMoreTokens()
Sprawdza, czy jest więcej podciągów.

Ta klasa jest nieco podobna do klasy Scanner, która również miała metody nextLine()i hasNextLine().

Możesz utworzyć obiekt StringTokenizerza pomocą polecenia:

StringTokenizer Nazwa = new StringTokenizer(строка, разделители);

Gdzie jest sznurek строка, który podzielimy na części. A разделителиjest ciągiem, którego każdy znak jest uważany za znak ogranicznika. Przykład:

Kod Wyjście na wyświetlaczu
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

Zauważ, że każdy znak ciągu przekazany jako drugi ciąg do konstruktora jest uważany za ogranicznik StringTokenizer.



2. Metoda String.format()i klasaStringFormatter

Inną interesującą metodą klasy String jest format().

Załóżmy, że masz różne zmienne danych. Jak wyświetlić je na ekranie w jednej linii? Na przykład mamy dane (lewa kolumna) i pożądane dane wyjściowe (prawa kolumna):

Kod Wyjście na wyświetlaczu
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Najprawdopodobniej Twój kod będzie wyglądał mniej więcej tak:

Kod programu
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

Taki kod jest mało czytelny. Co więcej, gdyby nazwy zmiennych były dłuższe, kod stałby się jeszcze bardziej skomplikowany:

Kod programu
class User {
    ......
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getFriends() {
        return friends;
    }

    public ExtraInformation getExtraInformation() {
        return extraInformation;
    }
}

User user = new User();

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

Mało czytelne, prawda?

Jednak w rzeczywistych programach taka sytuacja często występuje, dlatego chcę porozmawiać o sposobie napisania tego kodu w łatwiejszy i krótszy sposób.

String.format

Klasa String ma metodę statyczną format(): pozwala ustawić szablon łączenia łańcucha z danymi. Ogólna postać tego polecenia jest następująca:

String Nazwa = String.format(шаблон, параметры);

Przykład:

Kod Wynik
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

Metoda format()przekazuje jako pierwszy parametr łańcuch szablonowy, który zawiera cały potrzebny tekst, aw miejscach, w których trzeba wstawić dane, wpisywane są znaki specjalne typu %d, %sitp .

Te %si %dmetoda format()są zastępowane przez parametry następujące po łańcuchu szablonu. Jeśli musimy zastąpić ciąg, piszemy %s, jeśli liczba to %d. Przykład:

Kod Wynik
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
sbędzie równy"a=1, b=4, c=3"

Oto krótka lista parametrów, których można użyć w szablonie:

Symbol Przeznaczenie
%s
String
%d
liczba całkowita: byte, short, int,long
%f
liczba rzeczywista: float,double
%b
boolean
%c
char
%t
Date
%%
Symbol%

Te parametry wskazują typ danych, ale istnieje więcej parametrów wskazujących kolejność danych. Aby wziąć parametr według jego numeru (numeracja zaczyna się od jednego), musisz napisać zamiast . Przykład:%1$d%d

Kod Wynik
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
sbędzie równy"a=13, b=12, c=11"

%3$dweźmie trzecią zmienną-parametr, %2$dweźmie drugi parametr. %dprzyjmie pierwszą zmienną parametru. %sParametry szablonu %dodnoszą się do zmiennych parametrów niezależnie od parametrów szablonu typu %3$dlub%2$s



3. Basen smyczkowy

Wszystkie napisy, które zostały określone w kodzie jako literały są przechowywane w pamięci w tzw StringPool. StringPooljest specjalną tablicą do przechowywania ciągów znaków. Celem jego powstania jest optymalizacja przechowywania stringów:

Po pierwsze, łańcuchy określone w kodzie nadal muszą być gdzieś przechowywane. Kod to polecenia, a dane (zwłaszcza tak duże jak napisy) muszą być przechowywane w pamięci oddzielnie od kodu. Kod zawiera tylko odwołania do obiektów łańcuchowych.

Po drugie, wszystkie identyczne literały mogą być przechowywane w pamięci tylko raz. Tak to działa. Kiedy twój kod klasy jest ładowany przez maszynę Java, wszystkie literały łańcuchowe są dodawane, StringPooljeśli jeszcze ich tam nie ma. Jeśli już istnieje, po prostu używa linku do łańcucha z StringPool.

Więc jeśli przypiszesz te Stringsame literały do ​​wielu -zmiennych w swoim kodzie, zmienne będą zawierały te same odniesienia. Literał StringPoolzostanie dodany tylko raz, we wszystkich innych przypadkach zostanie pobrany link do już załadowanego do StringPoolłańcucha.

Jak to mniej więcej działa:

Kod Praca z StringPoolem
String a = "Cześć";
String b = "Cześć";
String c = "Пока";
String[] pool = {"Cześć", "Do widzenia"};
a = pool[0];
b = pool[0];
c = pool[1];

Dlatego zmienne abędą bprzechowywać te same referencje.

metodaintern()

Cóż, najciekawsza rzecz: możesz programowo dodać dowolną linię do StringPool. Aby to zrobić, wystarczy wywołać metodę intern()na String-zmiennej.

Metoda intern()doda ciąg do, StringPooljeśli jeszcze go tam nie ma, i zwróci odwołanie do ciągu z StringPool.

Jeśli do metody zostaną dodane dwa identyczne łańcuchy StringPoolprzy użyciu metody , metoda zwróci identyczne odwołania. intern()Można tego użyć do porównania ciągów znaków przez odniesienie. Przykład:

Kod Notatka
String a = new String("Cześć");
String b = new String("Cześć");
System.out.println(a == b);


false
String a = new String("Cześć");
String b = new String("Cześć");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

Jest mało prawdopodobne, że będziesz często korzystać z tej metody, ale lubią o to pytać na rozmowach kwalifikacyjnych , więc lepiej o tym wiedzieć, niż nie wiedzieć.