1. StringTokenizerклас

А сега още няколко общи сценария, включващи работа с низове. Как се разделя низ на няколко части? Има няколко начина да направите това.

split()метод

Първият начин за разделяне на низ на множество части е използването на split()метода. Регулярен израз, който дефинира специален разделящ низ, трябва да бъде подаден като аргумент. Ще научите Howво е регулярен израз в мисията Java Multithreading .

Пример:

Код Резултат
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
Резултатът ще бъде масив от три низа:
["Good ", "ws everyo", "!"]

Просто, но понякога този подход е прекален. Ако има много разделители (например интервали, знаци за нов ред, раздели, точки), тогава трябва да конструирате доста сложен регулярен израз. Трудно се чете и следователно трудно се променя.

StringTokenizerклас

Java има специален клас, чиято работа е да раздели низ на поднизове.

Този клас не използва регулярни изрази: instead of това просто предавате низ, състоящ се от разделители. Предимството на този подход е, че той не разбива целия низ на части наведнъж, а instead of това се движи от началото до края стъпка по стъпка.

Класът има конструктор и два важни метода. Предаваме на конструктора низ, който разделяме на части, и низ, съставен от набор от разделителни знаци.

Методи Описание
String nextToken()
Връща следващия подниз
boolean hasMoreTokens()
Проверява дали има още поднизове.

Този клас по няHowъв начин напомня на класа Scanner, който също има nextLine()и hashNextLine()методи.

Можете да създадете StringTokenizerобект с тази команда:

StringTokenizer name = new StringTokenizer(string, delimiters);

Къде stringе низът, който трябва да се раздели на части. И delimitersе низ и всеки знак в него се третира като разделител. Пример:

Код Конзолен изход
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
!

Имайте предвид, че всеки знак в низа, предаден като втори низ към StringTokenizerконструктора, се счита за разделител.



2. String.format()метод и StringFormatterклас

Друг интересен метод на класа String е format().

Да приемем, че имате различни променливи, съхраняващи данни. Как ги показвате на екрана в един ред? Например, имаме някои данни (лява колона) и желания резултат (дясна колона):

Код Конзолен изход
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Вашият code вероятно ще изглежда така:

Програмен code
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.}");

Такъв code не е много четим. И ако имената на променливите бяха по-дълги, тогава codeът щеше да стане още по-труден:

Програмен code
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.}");

Не е много четиво, нали?

Но това е често срещана ситуация в програмите от реалния свят, така че искам да ви разкажа за начин да напишете този code по-просто и по-сбито.

String.format

Класът String има статичен format()метод: той ви позволява да посочите модел за сглобяване на низ с данни. Общият вид на командата е следният:

String name = String.format(pattern, parameters);

Пример:

Код Резултат
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

Първият format()параметър на метода е форматиращ низ, който съдържа целия желан текст заедно със специални знаци, наречени спецификатори на формат (като %dи %s) на местата, където трябва да вмъкнете данни.

Методът format()замества тези %sи %dспецификаторите на формат с параметрите, които следват форматния низ в списъка с параметри. Ако искаме да вмъкнем низ, тогава пишем %s. Ако искаме да вмъкнем число, тогава спецификаторът на формата е %d. Пример:

Код Резултат
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
sе равно на"a=1, b=4, c=3"

Ето кратък списък със спецификатори на формат, които могат да се използват във форматния низ:

Спецификатор Значение
%s
String
%d
число: byte, short, int,long
%f
реално число: float,double
%b
boolean
%c
char
%t
Date
%%
%характер

Тези спецификатори указват типа на данните, но има и спецификатори, които указват реда на данните. За да получите аргумент по неговия номер (номерацията започва от единица), трябва да напишете " " instead of " ". Пример:%1$d%d

Код Резултат
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
sе равно на"a=13, b=12, c=11"

%3$dще получи третия аргумент, %2$dще получи втория аргумент и %dще получи първия аргумент. Спецификаторите %sи %dформат се отнасят до аргументи, независимо от спецификаторите като %3$dor%2$s



3. Пул от низове

Всеки низ, указан в codeа като низов литерал, се съхранява в област от паметта, наречена докато StringPoolпрограмата работи. StringPoolе специален масив за съхранение на низове. Целта му е да оптимизира съхранението на низове:

Първо, низовете, посочени в codeа, трябва да се съхраняват някъде, нали? Кодът се състои от команди, но данните (особено големите низове) трябва да се съхраняват в паметта отделно от codeа. В codeа се появяват само препратки към низови обекти.

Второ, всички идентични низови литерали трябва да се съхраняват в паметта само веднъж. И това е просто How работи. Когато codeът на вашия клас се зарежда от Java машината, всички низови литерали се добавят към, StringPoolако вече не са там. Ако те вече са там, тогава просто използваме препратка към низ от StringPool.

Съответно, ако присвоите един и същ литерал на няколко Stringпроменливи във вашия code, тогава тези променливи ще съдържат една и съща препратка. Към единствения веднъж ще бъде добавен литерал StringPool. Във всички останали случаи codeът ще получи препратка към низа, който вече е зареден в StringPool.

Ето How работи приблизително:

Код Работа с StringPool
String a = "Hello";
String b = "Hello";
String c = "Bye";
String[] pool = {"Hello", "Bye"};
a = pool[0];
b = pool[0];
c = pool[1];

Ето защо променливите aи bще съхраняват едни и същи препратки.

intern()метод

И най-добрата част е, че можете програмно да добавите всеки низ към StringPool. За да направите това, просто трябва да извикате метода Stringна променливата intern().

Методът intern()ще добави низа към, StringPoolако вече не е там, и ще върне препратка към низа в StringPool.

StringPoolАко към метода се добавят два еднакви низа intern(), методът връща същата препратка. Това може да се използва за сравняване на низове чрез препратка. Пример:

Код Забележка
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);


false
String a = new String("Hello");
String b = new String("Hello");

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





false
true

Малко вероятно е да използвате този метод често, но хората обичат да питат за него в интервюта . Така че е по-добре да знаете за това, отколкото да не знаете.