Освоюємо Java/Рядки
Рядок (англ. string) в java — це послідовність символів Юнікоду. Наприклад: "Абвгґд". В багатьох мовах програмування рядки зберігаються у масивах. Проте в java рядки представляють собою окремий об'єктний тип. Для рядків може використовуватись оператор "+", що здійснює конкатенацію(з'єднання) двох окремих рядків. Так в розглянутих навчальних прикладах конкатенація використовується при виводі на консоль System.out.println("Один" + "два" + "=" + "Три")
. Для здійснення інших дій з рядками, як то пошук символів та буквосполучень, використовуються методи класу String.
Спецсимволи
[ред.]Оголошення змінної і присвоєння їй рядка відбувається наступним чином:
String str = "Це рядок";
Для того щоб створити рядок, необхідно взяти літери в подвійні лапки: "це рядок"
. Також можна створити пустий рядок "". Якщо необхідно використати спецсимволи, то застосовують зворотню косу (backslash) "\". Наприклад, помістити в рядок внутрішні подвійні лапки можна таким чином "\" - це лапка"
. Аналогічно для одинарних лапок, недрукованих символів, тощо. Найчастіше коса застосовується для символу нового рядка:
System.out.println("Це перший рядок тексту, \nа це другий текстовий рядок.");
Таким чином рядок (string) може містити текст з кількома текстовими рядками (в англ. застосовують термін multiline string — багатолінійний рядок, багаторядковий рядок або ж багаторядкова стрічка). Проте власне клас String не дуже підходить для зберігання великих об'ємів текстових даних та маніпуляцій з ними. Для цього краще застосовувати класи StringBuilder або ж StringBuffer.
Конкатенація
[ред.]Як вже було сказано конкатенація - це поєднання двох рядків, що здійснюється за допомогою оператора "+". Таким чином наступні рядки здійснюють одне й те саме:
String str = "Це рядок";
String str = "Це"+" рядок";
При використанні конкатенації рядків з іншими типами даних відбувається автоматичне приведення до типу String.
System.out.println(2 + "+" + 2 + "=" + "4 (чотири)");
String str3 = "цифра " + 5; //String + int дає String "цифра 5"
Також з'єднання двох рядків можна здійснити за допомогою методу concat():
String strEnd = "рулить";
String str = "Java ".concat(strEnd); //в результаті str="Java рулить"
Робота з рядками
[ред.]В java об'єкти класу String не можна змінювати. На перший погляд — це додає проблем при роботі, але насправді це не так. Не можна змінювати сам рядок в пам'яті комп'ютера, але змінній, яка посилається на певний рядок, можна призначити інший рядок.
String str = "Це";
String str2 = "рядок";
String str3 = "555";
str = str3; //так можна
str = str + " " + str2; //і так можна
Дію обмеження ви відчуєте, лише коли захочете, наприклад, замінити букву "е" на якусь іншу, або змінити її регістр. В інших мовах - це можна зробити без проблем. В java потрібно утворити новий рядок. Скопіювавши, наприклад, букву "Ц" і додавши до неї "Е". Рядок, на який вже не посилається жодна змінна, буде видалений з пам'яті комп'ютера автоматичним прибиральником сміття java.
В разі, якщо ж все ж таки необхідна маніпуляція з рядком напряму, то для таких цілей існують споріднені із String класи. Зокрема, StringBuffer — корисний, при роботі з великими об'ємами текстових даних, читання з файлу і т.п.
Щоб здійснити такі дії як пошук, заміна і т.п. в класі String існує чималий набір методів. Так, щоб дізнатися довжину рядка можна скористатися методом length()
:
String str = "Це рядок";
int strLength = str.length();
int str2Length = "Це рядок".length(); //можна і так
Як бачимо виклик методів відбувається як при роботі із класами, з використанням оператору «.» (точка): «об'єкт.метод()» або «об'єктна_змінна.метод()».
Підрядки
[ред.]Для того, щоб одержати частину рядка (підрядок) з іншого більшого рядка можна скористатися методом substring(pos1, pos2) класу String.
Наприклад:
String greeting = "Hello";
String s = greeting.substring(0,3); //скопіювати з greeting символи з 0 до 3, тобто 0, 1 та 2 – “Hel”
В результаті було скопійовано перших три символи. Символи в рядку нумеруються починаючи з нуля. Можна розрахувати довжину отриманого рядка: pos2-pos1. В даному випадку 3-0=3;
Як вже згадувалось ми, не можемо змінювати рядки. Тому, якщо ми, наприклад, захочемо змінити рядок Hello на Help без застосування додаткової змінної, можна скористатися методом substring() та оператором конкатенації «+»:
greeting = greeting.substring(0, 3) + "p!";
В результаті в greeting=“Help!”. Таким чином ми не змінюємо сам рядок, а присвоюємо змінній інший рядок.
Порівняння рядків
[ред.]Для того, щоб порівняти два рядки на рівність можна скористатися методом equals():
str1.equals(str2);
Метод повертає true, якщо str1 та str2 рівні, інакше false. Можна також, замість змінних str1, str2 застосовувати рядкові константи. Наприклад:
«Hello».equals(greeting);
Згаданий метод порівнює рядки з врахування регістру символів. Для того, щоб не враховувався регістр при порівнянні існує метод equalsIgnoreCase().
"Hello".equalsIgnoreCase("hello").
Не використовуйте оператор ==, щоб перевірити рядки на рівність. Таким чином лише перевіряється, чи рядки розташовуються за одним місцем в пам'яті, крім того, результат може бути неоднозначним. Так, якщо ми
String str1 = "Hello";
String str2 = "Hello";
if (str1 == str2)
System.out.println("рівні");
else
System.out.println("не рівні"); //скоріше всього на екрані отримаємо напис «рівні».
Неоднозначність результату пов'язана з тим, що константні рядки в java можуть специфічним чином розподілятися (share) в пам'яті для спільного використання змінними. Хоча може бути, що існуватиме багато копій однакових рядків.
Зауважте, що це не відноситься до рядків, які створені в результаті операцій «+» чи substring:
String str1 = "Hello";
String str2 = str1.substring(0,3) + "lo";
if (str1 == str2)
System.out.println("рівні");
else
System.out.println("не рівні"); //скоріше всього на екрані отримаємо напис «не рівні».
Приведення до типу
[ред.]Часто постає необхідність явного приведення типу String до інших типів і навпаки. Наприклад, ви вводите з клавіатури певне число, воно буде у вигляді рядка символів, а для проведення обчислень його потрібно привести або до типу int, якщо це цілочисельне число, або ж до float чи double, якщо дробове. Для таких випадків слугує ряд статичних методів valueOf(), які наявні в класі String, а також в класах, які реалізовують числові типи Float, Double та ін.
Наступна програма вимагає введення числа з клавіатури і виводить результат перемноження введеного числа та 36:
import java.util.Scanner;
public class TestValueOf {
public static void main(String[] args) {
int intNumber = 36;
System.out.print("Введіть число: ");
//зчитуємо число з клавіатури
Scanner in = new Scanner(System.in);
String doubleStr = in.next();
System.out.println("Ви ввели: " + doubleStr);
//Ціла і дробова частина повинна бути через крапку
//шукаємо чи не ввели через кому
int index = doubleStr.indexOf(",");
if (index >= 0) {
System.out.println("Кома у позиції: " + index);
doubleStr = doubleStr.replace(',', '.'); //замінити кому на крапку
}
//Перетворюємо int число у рядок тексту
String strNumber = String.valueOf(intNumber);
//Приєднуємо число до рядка через метод concat (хоча можна і оператором "+")
String strOut = "*".concat(strNumber) + "=";
//Перетворюємо введений рядок тексту у число
double number = Double.valueOf(doubleStr);
number = number * intNumber; //множимо введене число на 36
System.out.println(doubleStr + strOut + number);
}
}
Результат виконання:
Введіть число: 555,5 Ви ввели: 555,5 Кома у позиції: 3 555.5*36=19998.0
У наведеному прикладі для знаходження коми використано метод int indexOf(String str)
, а для заміни коми на крапку метод String replace(char oldChar, char newChar)
. Якщо не зробити таку заміну, то при приведенні типу String до Double виникне помилка виконання і програма завершиться аварійно.
За бажаннями, Ви можете ускладнити програму додавши перевірку на наявність непотрібних символів у введеному рядку і відкидання їх. Для вирішення цієї задачі скористайтесь списком методів, що наведений нижче в пункті розділу під назвою "String API".
Кодові точки та кодові одиниці
[ред.]В мові Java рядки організовані як послідовність значень типу char. Значення char представляються в Unicode 16 і являють собою кодову одиницю (Code Units). Найбільш часто використовувані символи Unicode представляються однією кодовою одиницею і також являють собою кодові точки(Code Points). Проте специфічні рідковживані символи представляються двома кодовими одиницями. Ці дві кодові одиниці не будуть являти собою дві кодові точки, вони утворюють одну кодову точку. Якщо в рядку є такі символи то метод length() повертатиме неправильну символьну довжину, по суті він повертатиме кількість кодових одиниць, а не кількість справжніх символів(кодових точок).
Тому, якщо такі символи можливі в рядках, то необхідно використовувати методи для роботи з кодовими точками. Наприклад, щоб визначити справжню кількість символів, потрібно визначити кількість кодових точок в рядку методом codePointCount:
int cpCount = greeting.codePointCount(0, greeting.length());
Також існують методи для отримання кодової точки з рядка, перевірки чи значення char отримане з рядка не є складовою кодової точки.
String API
[ред.]Клас String в Java містить понад 50 методів, які можуть бути корисні при програмуванні. Нижче наведено список з найбільш корисних методів. Детальніше про методи дивіться у документації по String.
Тип повернення |
Назва методу та його аргументи | Опис |
---|---|---|
char | charAt(int index) | Повертає char значення за вказаним індексом |
int | codePointAt(int index) | Повертає символ (Unicode code point) за вказаним індексом |
int | codePointBefore(int index) | Повертає символ (Unicode code point) перед вказаним індексом |
int | codePointCount(int beginIndex, int endIndex) | Повертає кількість кодових точок Unicode у зазначеному інтервалі в рядку. |
int | compareTo(String anotherString) | Порівнює два рядки лексикографічно |
int | compareToIgnoreCase(String str) | Порівнює два рядки лексикографічно, ігноруючи різницю в регістрах літер |
String | concat(String str) | приєднує зазначений рядок str в кінець рядка |
boolean | contains(CharSequence s) | Повертає true, тільки якщо рядок містить зазначену послідовність значень char |
boolean | contentEquals(CharSequence cs) | Порівнює рядок із зазначеною послідовністю символів(CharSequence) |
boolean | endsWith(String suffix) | Перевіряє чи рядок закінчується зазначеним суфіксом |
boolean | equals(Object anObject) | Порівнює рядок із зазначеним об'єктом |
boolean | equalsIgnoreCase(String anotherString) | Порівнює рядок з іншим рядком, ігноруючи регістр |
byte[] | getBytes() | Кодує рядок у послідовність байт використовуючи символьний набір(charset) по замовчуванню, результат зберігається у новому байтовому масиві |
byte[] | getBytes(Charset charset) | Кодує рядок у послідовність байт використовуючи наданий символьний набір(charset), результат зберігається у новий байтовий масив |
byte[] | getBytes(String charsetName) | кодує рядок у послідовність байт використовуючи названий символьний набір, результат зберігається у новому байтовому масиві |
void | getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) | Копіює символи з рядка у символьний масив |
int | hashCode() | Повертає ГЕШ-код для рядка |
int | indexOf(int ch) | Повертає індекс першого входження зазначеного символу в рядок |
int | indexOf(int ch, int fromIndex) | Повертає індекс символу у рядку починаючи пошук із зазначеного індексу |
int | indexOf(String str) | Повертає індекс першого знаходження підрядка у рядку |
int | indexOf(String str, int fromIndex) | Повертає індекс в рядку підрядка, починаючи пошук із зазначеної позиції |
boolean | isEmpty() | Повертає true, тільки тоді, якщо довжина(length()) становить 0. |
int | lastIndexOf(int ch) | Повертає індекс останнього входження зазначеного символу в рядку |
int | lastIndexOf(int ch, int fromIndex) | Повертає індекс останнього входження зазначеного символу, шукаючи його із зазначеної позиції в рядку |
int | lastIndexOf(String str) | Повертає індекс останнього входження зазначеного підрядка |
int | lastIndexOf(String str, int fromIndex) | Повертає індекс останнього входження зазначеного підрядка, шукаючи його із зазначеного індексу у рядку |
int | length() | Повертає довжину даного рядка |
boolean | matches(String regex) | Говорить чи відповідає даний рядок заданому регулярному виразу |
String | replace(char oldChar, char newChar) | Повертає новий рядок заміняючи усі входження символу(oldChar) в рядку на новий символ (newChar) |
String | replace(CharSequence target, CharSequence replacement) | Заміняє в рядку підрядок target новою послідовністю replacement |
String | replaceAll(String regex, String replacement) | Заміняє кожен підрядок в рядку, що співпадає з регулярним виразом(regex) новим підрядком(replacement) |
String | replaceFirst(String regex, String replacement) | Заміняє перший підрядок, що відповідає заданому регулярному виразу на підрядок для заміни |
String[] | split(String regex) | Розбиває рядок за певним правилом поданим у регулярному виразі |
String[] | split(String regex, int limit) | Розбиває рядок за певним правилом поданим у регулярному виразі |
boolean | startsWith(String prefix) | Перевіряє чи поточний рядок починається з заданого префікса |
String | substring(int beginIndex) | Повертає підрядок з поточного рядка |
String | substring(int beginIndex, int endIndex) | Повертає підрядок з поточного рядка |
char[] | toCharArray() | Перетворює рядок у новий символьний масив |
String | toLowerCase() | Перетворює усі символи рядка у нижній регістр використовуючи locale правило по замовчуванню |
String | toLowerCase(Locale locale) | Перетворює усі символи рядка у нижній регістр використовуючи правило Locale. |
String | toUpperCase() | Конвертує всі символи рядка у верхній регістр використовуючи locale правило по замовчуванню |
String | toUpperCase(Locale locale) | Перетворює усі символи рядка у верхній регістр використовуюче правило подане у Locale. |
String | trim() | Повертає копію рядка усуваючи пробіли спереду і ззаду рядка |
static String | valueOf(boolean b) | Повертає рядкове представлення аргументу boolean типу |
static String | valueOf(char c) | Повертає рядкове представлення char аргументу |
static String | valueOf(char[] data) | Повертає рядкове представлення масиву типу char |
static String | valueOf(double d) | Повертає рядкове представлення double аргументу |
static String | valueOf(float f) | Повертає рядкове представлення float аргументу |
static String | valueOf(int i) | Повертає рядкове представлення int аргументу. |
static String | valueOf(long l) | Повертає рядкове представлення аргументу типу long |
static String | valueOf(Object obj) | Повертає представлення об'єкту у вигляді рядка |
StringBuilder
[ред.]Якщо необхідно часто змінювати рядок, то використовувати String доволі неефективно, для цього слугує клас StringBuilder (можна перекл. як будівник рядка). Об'єкти StringBuilder подібні до об'єктів String, лише з тією різницею, що їх можна модифікувати. По суті StringBuilder розроблений для роботи з великими рядками, в які часто необхідно вносити зміни. StringBuilder з’явився у JDK 5.0. Він майже повністю заміняє більш ранній клас StringBuffer, який дещо менш ефективний при роботі з рядками. Щоправда, новий клас StringBuilder орієнтований на роботу з одною ниттю (thread –нить або ж програмний потік). Якщо ж необхідна підтримка багатонитевості при роботі з рядком тексту, то слід використовувати StringBuffer. Робота з StringBuffer практично ідентична. Щоб використовувати клас StringBuilder, спочатку необхідно створити відповідний об'єкт:
StringBuilder builder = new StringBuilder();
Кожен раз, коли необхідно додати нову частину рядка, просто викличте метод append ():
builder.append(ch); // додаємо символ
builder.append(str); // додаємо рядок
Щоб передати результат у String:
String completedString = builder.toString();
Розглянемо усе більш детальніше. Клас StringBuilder, як і клас String має метод length(), що повертає довжину символьної послідовності в будівнику. Проте крім довжини будівник також має ємність — кількість символів, яку він може вмістити. Ємність можна одержати методом Capasity(). Загалом вона дорівнює довжині, або ж більша за неї. При збільшенні рядка ємність автоматично збільшується.
Конструктор | Опис |
---|---|
StringBuilder() | Створює пустий об'єкт StringBuilder з ємністю 16 (16 порожніх елементів). |
StringBuilder(CharSequence cs) | Створює об'єкт StringBuilder, що містить ту ж кількість символів як CharSequence, плюс 16 порожніх елементів вкінці. |
StringBuilder(int initCapacity) | Створює порожній об'єкт StringBuilder із заданою ємністю. |
StringBuilder(String s) | Створює об'єкт StringBuilder, ініціалізований заданим рядком String, плюс 16 додаткових порожніх елементів вкінці |
Клас StringBuilder має ряд методів пов'язаних з довжиною і ємністю, яких немає у класі String.
Метод | Опис |
---|---|
void setLength (int newLength) | Встановити довжину послідовності символів. Якщо нова довжина (newLength) менше ніж length(), символи, які виходять за межі даної довжини будуть відкинуті. Якщо newLength більша ніж length(), то в кінець послідовності додаються порожні (null) символи. |
void ensureCapacity (int minCapacity) | Гарантує, що ємність щонайменше рівна зазначеному мінімуму |
Основними операціями над StringBuilder, яких немає у String, є методи append() та insert(), що є перевантаженими і можуть приймати дані будь-яких типів. Кожен метод конвертує їхній аргумент у об'єкт String і згодом приєднує або вставляє символи даного рядка до символьної послідовності у об'єкті StringBuilder. Метод append() завжди додає символи в кінець існуючої послідовності, в той час як insert() додає символи всередину символьної послідовності.
Далі наведено перелік методів класу StringBuilder
Метод | Опис |
---|---|
StringBuilder append(boolean b) StringBuilder append(char c) |
Додати аргумент до об'єкту StringBuilder. Перед тим як дані приєднуються вони перетворюються у String. |
StringBuilder delete(int start, int end) StringBuilder deleteCharAt(int index) |
Перший метод видаляє символи послідовність починаючи з індексу start до end-1 (включно) . Другий методи видаляє символ розташований за відповідним індексом. |
StringBuilder insert(int offset, boolean b) StringBuilder insert(int offset, char c) |
Вставляє другий аргумент у послідовність. Перший цілочисельний аргумент вказує індекс перед яким дані вставляються. Перед операцією вставлення дані конвертуються у звичайний рядок String. |
StringBuilder replace(int start, int end, String s) void setCharAt(int index, char c) |
Заміняє зазначений символ(и) |
StringBuilder reverse() | Обертає символьну послідовність ззаду наперед |
String toString() | Повертає рядок типу String, що містить символьну послідовність екземпляру StringBuilder. |
Якщо Вам необхідні використати методи String, то можна просто перетворити StringBuilder у звичний String використовуючи метод toString. Згодом можна зробити зворотнє перетворення String у StringBuilder з використанням конструктора StringBuilder(String str).
public class StringBuilderTest {
public static void main(String args[]){
String str="Джонні";
StringBuilder strB=new StringBuilder(str); //створюємо об'єкт StringBuilder
strB.append(" та Еліс"); //приєднуємо до попереднього рядка новий
strB.reverse(); // обертаємо рядок задом на перед
System.out.println(strB);
}
}
Результат виконання:
сілЕ ат інножД