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. Як масив цілих чисел розташовується в пам'яті:

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

Також відома картинка.

Картинка 3. Як в пам’яті розташовується масив рядків:

Як в пам’яті розташовується String масив

Зліва ми бачимо змінну-масив типу 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[] { 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 Рівень 28
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
дуже помогло б, як би я побачив твій комент раніше десь на пару годин ) дяка