Всім привіт! Часто до наших методів приходять числа, які потрібно відобразити у якомусь особливому форматі. Начебто як дрібниця, але як би ви реалізували це завдання? Пропонуємо над цим сьогодні трохи поміркувати. Для початку, щоб з головою поринути у форматування чисел у Java, давайте згадаємо метод format класу String : public static String format(String format, Object ... args) - Повертає рядок, відформатований з рядка format за допомогою інших аргументів args . І одразу приклад:
Давайте використовуємо для double більш відповідний формат:
Це скорочений список можливих прапорів форматування дат – їх дуже багато, на будь-який смак. Повний список їх як і можливих специфікаторів можна переглянути за цим посиланням . Давайте розглянемо, як користуватися цим. На цей раз використовуємо не String.format() , а відразу System.out.printf() .
String str = String.format("Привіт %s! Як справи %s?", "Саша", "на роботі");
System.out.println(str);
У результаті ми отримаємо висновок у консолі:
Привіт Саша! Як справи на роботі?
Методи printf та format
String.format() — це не єдиний метод для форматування рядка. Його аналогами можуть бути System.out.printf() і System.out.format(); . Так, попередній код ми можемо замінити на:System.out.printf("Привіт %s! Як справи %s?", "Саша", "на роботі");
або
System.out.format("Привіт %s! Як справи %s?", "Саша", "на роботі");
Висновок у консолі при цьому залишиться тим самим. Єдиною відмінністю служить лише те, що ці методи відразу виводять значення консолі, на відміну String.format() . Але мені String.format() подобається більше, тому що нам не завжди потрібно виводити результат у консолі, тому далі ми використовуватимемо саме цей спосіб. Повернімося до нашого прикладу. Що ми бачимо? А те, що в місця, де були символи - %s , вставлені рядки - "Саша" та "на роботі". Яким чином це може нам допомогти при розробці? Уявіть, що у вас є великий шаблонний текст, але в деяких місцях потрібно вставляти значення, які можуть бути різними і приходити в якості аргументів ззовні. Ось тут нам і знадобиться це форматування. Специфікатори формату починаються зі знака відсотка % і закінчуються символом, що вказує на тип аргументу, який потрібно відформатувати. І, як ви, напевно, зрозуміли, %s використовується для вставки об'єктів — рядків. Але якщо ми спробуємо вставити, наприклад, double в місце, де прописаний об'єкт рядка:
String str = String.format("Привіт %s! Як справи %s?", 55.6, "на роботі");
це також спрацює. double буде приведено до рядка, і ми отримаємо:
Привіт – 55.6! Як справи на роботі?
Крім рядків і чисел з плаваючою комою, у Java є й інші типи, чи не так? Тож давайте поглянемо на весь арсенал:
Тип форматованого значення | приклад | |
---|---|---|
%s | Будь-який тип, який буде приведений до рядка |
Результат:
Привіт світ!
|
%b | Будь-який тип, який буде приведений до boolean : true – якщо значення не null, false – якщо null |
Результат:
Привіт false
|
%h | Можна передавати будь-який об'єкт, який буде приведений до шістнадцяткового рядка значення з методу hashCode () |
Результат:
Привіт 106C44!
|
%c | Використовується для завдання символу Unicode ( char ) |
Результат:
Привіт світ!
|
%d | Задається ціле число ( int. byte, short, int, long, BigInteger ) |
Результат:
Мені вже 20!
|
%f | Використовується для завдання числа з плаваючою комою |
Результат:
Число ПІ дорівнює - 3,141590!
|
%e | Числа з плаваючою комою в експоненційному поданні |
Результат:
Число ПІ дорівнює - 3,141590e+00!
|
%a | Числа з плаваючою комою будуть представлені у шістнадцятковому вигляді |
Результат:
Число ПІ дорівнює - 0x1.921f9f01b866ep1!
|
%x | Передається ціле число ( int. byte, short, int, long, BigInteger ), результатом форматування буде символ під цим номером у таблиці ASCII |
Результат:
Мені вже 19!
|
%o | Приймається ціле число ( int. byte, short, int, long, BigInteger ), яке буде представлено у вигляді восьмеричного числа |
Результат:
Мені вже 31!
|
%t | Префікс для перетворення дати та часу. Для форматування потрібні додаткові прапори |
Результат:
Сьогодні субота
|
%n | Розділювач рядків для конкретної платформи. Аналог \n |
Результат:
Привіт привіт
|
String str = String.format("Відстань від Києва до Одеси - %f. Не так уже й мало, чи не так?", 475.4d);
System.out.println(str);
Виведення в консоль:
Відстань від Києва до Одеси – 475,400000. Не так уже й мало, чи не так?
Як ви вже зрозуміли, %f буде більш відповідним специфікатором для чисел з плаваючою комою, які включають такі типи даних як double і float в Java. З цим специфікатором ми можемо форматувати число з плаваючою комою:
String str = String.format("Відстань від Києва до Одеси - %.2f. Не так уже й мало, чи не так?", 475.4d);
Вставка .2 в даний специфікатор обріже кількість знаків після коми до двох, і ми отримаємо висновок:
Відстань від Києва до Одеси – 475,40. Не так уже й мало, чи не так?
.2 - не єдина підналаштування специфікаторів. Комбінація даних підналаштувань називається інструкцією . Загальний вигляд інструкції такий:
%[аргумент_індекс][прапори][ширина][.точність]специфікатор типу
А тепер розшифруємо все по порядку:
- [аргумент_індекс] — ціле число, що вказує на позицію в списку аргументів. Наприклад, посилання перший аргумент 1$, посилання другий аргумент — 2$, тощо. Якщо ж позиція не була задана, аргументи повинні бути в тому ж порядку, що й посилання на них у форматі.
- [Прапори] — спеціальні символи для форматування. Наприклад:
- + прапор, що означає, що якщо числове значення позитивне, воно має містити знак +
- - означає вирівнювання результату з лівого краю
- , встановлює роздільник тисяч у цілих чисел
- [Ширина] — позитивне ціле десяткове число, що визначає мінімальну кількість символів, які будуть виведені. Якщо перед цим числом стоїть 0, то символи, що відсутні, будуть доповнені 0, якщо 0 ні, то пробілами.
- [. Точність] - невід'ємне ціле число з точкою перед ним. Як правило, використовується для обмеження кількості символів. Специфіка поведінки залежить від виду специфікатора.
String str = String.format("%1$+09.5f", 3.1415926535897);
System.out.print(str);
І, відповідно, висновок у консолі:
+03,14159
Начебто нескладно, так? Але коли йдеться про форматування числа, то не можна обійти стороною DecimalFormat . Давайте розберемося, що мають на увазі.
DecimalFormat
DecimalFormat - клас для форматування будь-якого числа в Java, чи то ціле число, чи число з плаваючою комою. Коли відбувається створення об'єкта DecimalFormat , прямо в конструкторі можна задати шаблон форматування чисел, що приходять. Як буде виглядати наш приклад з використанням DecimalFormat :DecimalFormat dF = new DecimalFormat( "#.###" );
double value = 72.224463;
System.out.print(dF.format(value));
Висновок у консолі:
72,224
Рядок #.### є шаблоном, який вказує, що ми форматуємо значення, що передається, до 3 десяткових знаків. Які ще є символи для шаблонів? Ось деякі з них:
- # - цифра, що ведуть нулі опускаються;
- 0 — цифра завжди відображається, навіть якщо в номері менше цифр (у такому випадку відображається 0);
- . - Знак десяткового роздільника;
- , - Знак угруповання роздільників (наприклад, роздільник тисяч);
- ; - Поділяє формати;
- - - Зазначає префікс негативного числа;
- % - множить на 100 і показує число у відсотках;
- ? - множить на 1000 і показує число у проміле;
- E – розділяє мантису та порядок для експоненційного формату.
System.out.println(new DecimalFormat( "###,###.##" ).format(74554542.224463));
Висновок у консолі:
74 554 542,22
System.out.println(new DecimalFormat( "%###.##" ).format(0.723456));
Висновок у консолі:
%72,35
System.out.println(new DecimalFormat( "000.###" ).format(42.224463));
Висновок у консолі:
042,224
Не обов'язково створювати щоразу новий об'єкт DecimalFormat , щоб задати новий шаблон. Досить використовувати його методи applyPattern і applyLocalizedPattern :
DecimalFormat dF = new DecimalFormat("###.###");
dF.applyPattern("000000.000");
dF.applyLocalizedPattern("#,#00.0#");
Коли ми говоримо про форматування числа з плаваючою комою, нас чимало цікавить округлення, чи не так? Так ось, при обрізанні числа зі знаками після коми, що виходять за заданий шаблон, DecimalFormat округляє число у більшу сторону, якщо останнє число, що обрізається, більше 5. А якщо останнє обрізуване - 5? Адже в такому разі це число рівно посередині між найближчими цілими. У цьому випадку до уваги береться попереднє до нього число. Якщо попереднє число парне, округлення провадиться:
DecimalFormat dF = new DecimalFormat("##.###");
String result = dF.format(56.4595);
System.out.println((result));
Висновок у консолі:
56,459
Якщо непарне — не робиться:
DecimalFormat dF = new DecimalFormat("##.###");
String str = dF.format(56.4595);
System.out.println((str));
Висновок у консолі:
56,459
Різницею між форматуванням чисел з плаваючою комою з використанням String.format() і DecimalFormat.format() можна вважати те, що в першому випадку будуть присутні кінцеві нулі, навіть якщо немає дробової частини. Наприклад:
String firstStr = String.format("%.4f", 9.00001273);
System.out.println((firstStr));
Висновок у консолі:
9,0000
DecimalFormat decimalFormat = new DecimalFormat("#.####");
String secondStr = decimalFormat.format(9.00001273);
System.out.println((secondStr));
Висновок у консолі:
9
Як бачите, при форматуванні числа 9.00001273 з точністю до чотирьох десяткових розрядів метод format() у класу String виведе значення 9.0000 , при цьому у DecimalFormat аналогічний метод format() виведе 9 .
BigDecimal та BigInteger
Якщо ми торкнулися такої теми округлення чисел у Java, поговоримо і про те, як для таких операцій використовувати клас BigDecimal . Цей клас орієнтований працювати з справді ВЕЛИКИМИ числами: йому максимальні значення double і float занадто малі. Цей клас має багато різних налаштувань для округлення числа з плаваючою комою, а також багато методів для арифметичних операцій. Він має схожий клас, але орієнтований працювати з ВЕЛИКИМИ цілими числами — BigInteger . Докладніше про BigDecimal та BigInteger можна почитати в цій статті .Форматування Date та Time
Вище згадувалося, що за допомогою format() класу String можна ще й форматувати час і дату. Що ж, погляньмо, як це робиться. По-перше, хотілося б нагадати, що для дат використовується специфікатор формату %t . По-друге, при форматуванні шаблону для кожного специфікатора формату для дат потрібні додаткові прапори форматування. Ось можливі прапори форматування для дат:Прапори | Опис |
---|---|
%tB | Повна назва місяця, наприклад January, February і т.д. |
%tb | Скорочену назву місяця, наприклад, Jan, Feb тощо. |
%tA | Повна назва дня тижня, наприклад, Sunday, Monday |
%ta | Скорочену назву дня тижня, наприклад, Sun, Mon тощо. |
%tY | Рік у форматі 4 цифри, наприклад, від 0000 до 9999 |
%ty | Рік у форматі 2 цифри, наприклад, від 00 до 99 |
%tm | Місяць відформатовано з нуля на початку, наприклад, від 01 до 12 |
%tc | Дата та час у форматі %ta %tb %td %tT %tZ %tY, наприклад, Mon Feb 17 03:56:12 PST 2020 |
%tD | Дата у форматі %tm/%td/%ty |
%td | День місяця у форматі двох цифр, наприклад, від 01 до 31 |
%te | День місяця у форматі без 0 на початку, наприклад, від 1 до 31 |
%tT | Час у 24-годинному форматі, наприклад, %tH:%tM:%tS |
%tH | Година дня у 24-годинному форматі, від 00 до 23 |
%tI | Година дня для 12-годинного формату, наприклад, від 01 до 12 |
%tM | Хвабони за годину форматуються з нуля на початку, наприклад, від 00 до 59 |
%tS | Секунди за хвабону, що складаються з двох цифр, наприклад, від 00 до 59 |
%tZ | Абревіатура часового поясу, наприклад PST, UTC і т.д. |
Приклад 1
Крім того, поставимо мову результату, передавши її першим аргументом у спосіб:Date date = new Date();
System.out.printf(Locale.ENGLISH,"%tB %te, %tY",date,date,date);
Висновок у консолі:
October 11, 2020
Без задання мови буде використана мова за умовчанням (наприклад, у мене вона російська).
Приклад 2
Давайте виведемо на екран більш повну дату:Date date = new Date();
System.out.printf("%td %tB %tY року %n%tH:%tM:%tS",date,date,date,date,date,date,date);
І висновок у консолі:
11 жовтня 2020 13:43:22
Стільки разів передавати аргументом один і той самий об'єкт Date... Якось виглядає не дуже, чи не так? Давайте скористаємося внутрішньою підналаштуванням $ для вказівки аргументу, який ми хочемо використовувати:
System.out.printf("%1$td %1$tB %1$tY року %n%1$tH:%1$tM:%1$tS",date);
Висновок у консолі у нас і не зміниться. Є й інші не менш цікаві способи форматування дати. Про них і трохи докладніше про час і дату в Java можна почитати ось у цьому матеріалі . На цьому у мене на сьогодні все, дякую за увагу!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ