JavaRush /Курси /Java Syntax Zero /Поглиблена робота з масивами

Поглиблена робота з масивами

Java Syntax Zero
Рівень 6 , Лекція 4
Відкрита

1. Масив типу String

Ну і далі хотілося б стисло розповісти про масив типу String.

Як ми вже зазначали, масив може бути будь-якого типу. А отже, можна створити масив типу String. Отакий вигляд мав би код, якби нам потрібно було написати програму, що «вводить з клавіатури 10 рядків і виводить їх на екран у зворотному порядку».

Scanner console = new Scanner(System.in);
String[] array = new String[10];
for (int i = 0; i < 10; i++)
{
   array[i] = console.nextLine();
}
for (int i = 9; i >= 0; i--)
{
   System.out.println(array[i]);
}
Створюємо об'єкт Scanner
Створюємо об'єкт-масив на 10 елементів
Цикл від 0 до 9

Читаємо з клавіатури рядок і зберігаємо його в чергову комірку масиву
Цикл від 9 до 0

Виводимо на екран чергову комірку масиву

Код майже не змінився! Довелося тільки під час створення масиву замінити тип int на String, а для зчитування рядка з клавіатури замінити метод nextInt() на nextLine().


2. Масив типу String у пам'яті

І ще один корисний факт. Розгляньмо 3 малюнки:

Малюнок 1. Як об'єкт String розташований у пам'яті:

Об'єкт типу String у пам'яті

Цей малюнок ми взяли з попередніх лекцій.

Звертаємо вашу увагу, що текст рядка не зберігається безпосередньо в змінній: для нього виділяється окремий блок пам'яті. А в змінній типу String зберігається адреса (посилання) на об'єкт із текстом.

Малюнок 2. Як масив цілих чисел розташований у пам'яті:

Теж знайомий малюнок.

Малюнок 3. Як розташований у пам'яті масив рядків:

Ліворуч ми бачимо змінну-масив типу String[] (зберігає адресу об'єкта-масиву).

У центрі — об'єкт-масив типу String.

А праворуч — об'єкти-рядки, в яких зберігаються якісь тексти.

У комірках об'єкта-масиву типу String зберігаються не самі рядки (тексти), а їхні адреси (посилання). Так само, як у змінних типу String зберігаються адреси рядків (тексту).

Враховуйте цей факт, коли порівнюватимете комірки масиву:

String[] array = new String[10];
 array[1] = "Привіт";
array[2] = array[1];
array[3] = new String("Привіт");
// порівнюємо
array[1] == array[2];
array[1] == array[3];
array[1].equals(array[3]);
array[1].equalsIgnoreCase(array[3]);
Створюємо масив на 10 рядків

Вносимо значення в масив



true (посилання однакові)
false (посилання неоднакові)
true (рядки однакові)
true (рядки також однакові)


3. Швидка ініціалізація масиву в Java

Масиви — дуже корисна річ, тому розробники Java доклали зусиль, щоби працювати з масивами було якомога зручніше.

І найперше, що вони зробили, — це спростили ініціалізацію масиву, внесення в нього початкових значень.

Адже дуже часто окрім даних, які програма звідкись зчитує, їй потрібні для роботи ще й свої внутрішні дані. Наприклад, нам потрібно зберігати в масиві кількість днів у кожному місяці. Отакий вигляд може мати цей код:

int[] months = new int[12];
months[0] = 31; // січень
months[1] = 28; // лютий
months[2] = 31; // березень
months[3] = 30; // квітень
months[4] = 31; // травень
months[5] = 30; // червень
months[6] = 31; // липень
months[7] = 31; // серпень
months[8] = 30; // вересень
months[9] = 31; // жовтень
months[10] = 30; // листопад
months[11] = 31; // грудень

Але є спосіб його скоротити — подякуймо авторам Java:

// кількість днів у місяцях року
int[] months = new int[12] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Можна просто перелічити через кому всі значення масиву!

Зручно, чи не так? Але й це ще не все.

Виявляється, компілятор може визначити тип контейнера (об'єкта-масиву) на основі типу змінної-масиву, а для визначення довжини масиву — банально підрахувати кількість елементів, написаних у фігурних дужках.

Отож цей код можна скоротити ще сильніше:

// кількість днів у місяцях року
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Хіба не краса? 🙂

Такий запис називається «швидка ініціалізація масиву». До речі, це працює не тільки для типу int...

// назви місяців року
String[] months = { "Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"};
Коментарі (38)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Stas Semenyuk_ЗСУ Рівень 18
1 лютого 2025
Цікава задача. У першій спробі пройти перевірку однакові рядки заміняв на "null"(саме в кавичках), не пройшло. ПОтім виправив без кавичок, почало видавати RuntimeException. І завдячуючи дебагу, виявив, що помилка йде при порівнянні null==null. Здав з другої спроби.
IronMan57 Рівень 28
20 листопада 2024
Взагалі було непогано, якби автори курсу щось написали б про особливості роботи зі значенням null. Про виклик методів об'єктами зі значенням null, про використання у різних виразах і т.і.
hidden #3500645 Рівень 30
22 листопада 2024
Я не думаю, що курс будуть якось оновлювати, якщо подивитися на 5 рівень, то там скріншоти Open JDK 14 і в описі, що це найновіша версія на момент створення лекції, тож можна зробити висновок, що курс не оновлювали з 2020 року десь по даті релізу. Так само і з IntelliJ Debug застаріла версія показується.
hidden #3500645 Рівень 30
22 листопада 2024
Особливості роботи зі значенням null у Java У Java значення null представляє відсутність посилання на об'єкт. Робота зі значенням null вимагає особливої уваги, оскільки спроби виклику методів або доступу до полів через null можуть призвести до NullPointerException. 1. Виклик методів об'єктами зі значенням null Якщо змінна, що має значення null, використовується для виклику методу, програма викидає NullPointerException під час виконання. Приклад:

String str = null;
System.out.println(str.length()); // NullPointerException
Як уникнути: 1. Перевірка на null:

if (str != null) {
    System.out.println(str.length());
}
2. Використання Optional (з Java 8):

Optional<String> optionalStr = Optional.ofNullable(str);
optionalStr.ifPresent(s -> System.out.println(s.length()));
2. Використання null у виразах a. Порівняння Ви можете порівнювати значення null за допомогою оператора ==:

String str = null;
System.out.println(str == null); // true
Порівняння null з об’єктом завжди повертає false:

String str = null;
System.out.println(str.equals("test")); // NullPointerException
Рекомендується використовувати метод із перевіркою:

"test".equals(str); // Безпечний варіант, поверне false
b. Умовні конструкції Значення null можна використовувати в умовних виразах:

String str = null;
if (str == null) {
    System.out.println("Значення відсутнє");
}
hidden #3500645 Рівень 30
22 листопада 2024
c. Присвоєння значень за замовчуванням Якщо змінна може бути null, можна призначити їй значення за замовчуванням:

String str = null;
String result = (str != null) ? str : "default";
System.out.println(result); // default
3. NullPointerException Найпоширеніша помилка при роботі з null. Викликається в наступних випадках: 1. Виклик методів через null:

String str = null;
str.length(); // NullPointerException
2. Доступ до полів через null:

class Test {
    String name;
}
Test obj = null;
System.out.println(obj.name); // NullPointerException
3. Масиви:

String[] arr = null;
System.out.println(arr.length); // NullPointerException
Як уникнути: Завжди перевіряйте змінні на null перед використанням. Використовуйте інструменти, як Optional. 4. Використання Optional Optional (з Java 8) допомагає уникнути роботи з null, додаючи обгортку навколо змінних

Optional<String> optional = Optional.ofNullable(null);

// Перевірка та виконання дії
optional.ifPresent(value -> System.out.println(value.length()));

// Повернення значення за замовчуванням
String result = optional.orElse("default");
System.out.println(result); // default
5. Null у колекціях У колекціях Java допускається використання null як елементу Але це може створити проблеми, наприклад, при використанні методів contains або фільтрації.

List<String> list = new ArrayList<>();
list.add(null);
System.out.println(list.get(0)); // null

hidden #3500645 Рівень 30
22 листопада 2024
6. Null у Java 14+ Починаючи з Java 14, NullPointerException можна налаштувати для покращення діагностики:

System.getProperties().setProperty("jdk.debug", "on");
String str = null;
System.out.println(str.length());
// Exception: Cannot invoke "String.length()" because "str" is null

Рекомендації 1. Уникайте використання null, якщо це можливо (використовуйте Optional, значення за замовчуванням). 2. Додавайте перевірки на null перед доступом до об'єкта. 3. Використовуйте сучасні конструкції, як Optional або об'єктні шаблони. 4. Працюйте з колекціями, уникаючи додавання null як значення.
IronMan57 Рівень 28
29 листопада 2024
Дарино, дуже дякую. 👍
hidden #3500645 Рівень 30
30 листопада 2024
будь ласка ☺️
IronMan57 Рівень 28
20 листопада 2024
В цій задачі дуже погано зроблена перевірка. В моєму рішенні нібито не виконувалась друга умова, тільки через те, що я в команді присвоєння елементу значення null звертався до нього через присвоєне раніше ім'я. Тобто в мене було: String sample = strings[i]; ... sample = null; і цей код не приймався до тих пір, поки останню команду не написав у виді: strings[i] = null; А перед цим в мене було ще шість варіантів рішення, які видавали потрібний результат, але не приймались.
Jaroslav Рівень 48
11 листопада 2024
Задачу в HARD однозначно Це якась жесть
Олександр Рівень 102
10 листопада 2024
Непогана задача, їй можна присвоїти клас HARD. 35 хв забрала. Треба обов'язково перевіряти для трьох однакових рядків.
Dmytrii Рівень 67
6 червня 2024
тот момент, когда мозгами ты понимаешь, что и как сделать, но на написание кода уходит час 🤪
Кирило Рівень 43
11 червня 2024
2 дня...
gummer Рівень 11
27 лютого 2024
Обожнюю десять (а то й більше разів) міняти ПРАВИЛЬНЕ рішення просто бо системі автоперевірки чимсь воно не подобається (наразі я вкотре застряг на моменті, коли система автоперевірки не вірить мені, що я зчитав 6 рядків та заповнив ними масив string, лол, та коли я коментую увесь код, котрий в мене написаний після заповнення масиву string, якимсь чудесном чином перший пункт завдання знову світиться зеленим) Апд.: методом тику та почергового розкоментовування частин коду я виявив, що перший пункт "ламається" через цей рядок коду, де я беру допоміжний масив badStrings та шукаю в ньому усі цілочисельні значення:

            if(badStrings[i]==(int)badStrings[i]){
                strings[badStrings[i]]=null;
            }
Апд.2: тринадцять спроб потому таки здав задачу, змінивши спосіб пошуку індексів стрінгів у badStrings. Але типу, камон, це якось не ок, коли автоперевірка ламається через те, що мій спосіб рішення трохи відрізняється від очікуваного, тим паче якщо від цього страждають вже давно правильно виконані підпункти. Буду вдячний, якщо розробники звернуть на мій випадок увагу.
tterribaess Рівень 6
31 січня 2024
виключення "nullpointerexception" виникає коли ми звертаємось до комірки масиву зі значенням null. Враховуйте це при виконання задачі: Видаляємо однакові рядки
tterribaess Рівень 6
31 січня 2024
Можливо, комусь допоможе: переконайтеся, що ваша програма вміє "видаляти" ВСІ однакові рядки. (Спробуйте для >2 однакових рядків)
Михайло Рівень 9 Expert
5 січня 2024
Можливо, комусь допоможе: переконайтеся, що ваша програма вміє "видаляти" ВСІ однакові рядки. (Спробуйте для >2 однакових рядків)
Viacheslav B. Рівень 1
29 січня 2024
дуже помогло б, як би я побачив твій комент раніше десь на пару годин ) дяка