JavaRush /Java блог /Random UA /ArrayList у Java

ArrayList у Java

Стаття з групи Random UA
Під час розробки часто буває складно передбачити, якого розміру знадобляться масиви. Тому функція динамічного виділення пам'яті під час роботи програми потрібна кожній мові програмування. Динамічним називається масив, розмір якого може змінитися під час виконання програми. У Java для такої мети існує клас ArrayList .

Що таке клас ArrayList?

ArrayList - реалізація змінного масиву інтерфейсу List, частина Collection Framework, який відповідає за список (або динамічний масив), розташований у пакеті java.utils. Цей клас реалізує всі необов'язкові операції зі списком та надає методи керування розміром масиву, який використовується для зберігання списку. В основі ArrayList лежить ідея динамічного масиву. А саме, можливість додавати та видаляти елементи, при цьому буде збільшуватись або зменшуватись у міру необхідності.

Що зберігає ArrayList?

Тільки типи посилань, будь-які об'єкти, включаючи сторонні класи. Рядки, потоки виведення, інші колекції. Для зберігання примітивних типів даних використовуються класи-обгортки.

Конструктори ArrayList

  1. ArrayList()

    Порожній конструктор із початковою ємністю внутрішнього масиву = 10.

    ArrayList<String> list = new ArrayList<>();

    У кутових дужках бажано вказати тип значень, що зберігаються. У прикладі вище - String.

  2. ArrayList(Collection <? extends E> c)

    Конструктор приймає іншу колекцію, створюючи новий масив із елементами переданої колекції:

    ArrayList<String> list2 = new ArrayList<>(list);

    Порядок елементів у новому списку співпадатиме з вихідним.

  3. ArrayList(int initialCapacity)

    Як параметр конструктора виступає значення початкового розміру внутрішнього масиву.

    ArrayList<String> list2 = new ArrayList<>(10000);

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

Методи ArrayList

    Нижче наведено основні методи ArrayList.

  • add(E e)

    Додає новий елемент до кінця списку. Повертає booleanзначення ( true - успіх, false - не додано):

    ArrayList<String> list = new ArrayList<>();
    list.add("Hello");
  • add(int index, E element)

    Додає елемент elementдо позиції index. При додаванні відбувається зсув всіх елементів праворуч від зазначеного індексу на 1 позицію праворуч:

    list.add(0, "Amigo");

    Дуже корисний, коли потрібно вставити елемент у довільне місце списку, проте для частих операцій вставки на початок і середину ArrayList може виявитися не дуже вдалим вибором - слід вивчити LinkedList.

  • addAll(Collection <? extends E> collection)

    Додавання всіх елементів колекції collection до списку в порядку їхнього розташування в collection.

  • addAll(int index, Collection <? extends E> collection)

    Додавання всіх елементів collectionдо списку, починаючи з індексу index. При цьому всі елементи зрушать праворуч на кількість елементів у списку collection:

    ArrayList<String> secondList = new ArrayList<>();
    secondList.addAll(list);
    System.out.println("Перше додавання: " + secondList);
    secondList.addAll(1, list);
    System.out.println("Друге додавання до середини: " + secondList);

    Висновок:

    
    Первое добавление: [Amigo, Hello]
    Второе добавление в середину: [Amigo, Amigo, Hello, Hello]

    Методи addAll()також повертають boolean-результат додавання елементів.

  • clear()

    Видалення всіх елементів зі списку.

  • clone()

    Повертає об'єкт-копію масиву:

    ArrayList<String> copyOfSecondList = (ArrayList<String>) secondList.clone();
    secondList.clear();
    System.out.println(copyOfSecondList);

    Висновок:

    
    [Amigo, Amigo, Hello, Hello]

    Слід звернути увагу, що метод clone()повертає Object, тому після його виклику потрібно зробити приведення до необхідного класу.

    Під час клонування створюється новий незалежний об'єкт. У прикладі показано, як очищення клонованого об'єкта не позначилося на складі його клона.

  • contains(Object o)

    Перевіряючи наявність об'єкта в списку, повертає booleanзначення.

    System.out.println(copyOfSecondList.contains("Hello"));
    System.out.println(copyOfSecondList.contains("Check"));

    Висновок:

    
    true
    false
  • ensureCapacity(int minCapacity)

    Збільшує розмір внутрішнього масиву, щоб вмістилася кількість елементів, переданих в minCapacity. Якщо масив досить місткий, ніякі перетворення не виробляються.

    Цей метод корисний, коли виникає потреба вмістити велику кількість елементів у кілька ітерацій. Наприклад, при створенні списку ємність його внутрішнього масиву - 10. При завантаженні даних по мережі вони обробляються асинхронними порціями і результати поміщаються в масив. Якщо очікується доставка 10 000 елементів, може бути неефективно просто додавати ці дані щоразу: достатньо буде на початку обробки викликати метод ensureCapaciry(10000)і записувати туди дані за необхідності.

  • forEach(Consumer<? super E> action)

    Обробити цикл ArrayList можна стандартними способами, цикл for:

    // Перший спосіб
    for(int i = 0; i< secondList.size(); i++) {
       System.out.println(secondList.get(i));
    }
    И цикл for-each:
    // Другий спосіб
    for(String s : secondList) {
       System.out.println(s);
    }

    У класі ArrayList є метод обробки кожного елемента, який називається також, длякожного. Як аргумент передається реалізація інтерфейсу Consumer, в якому потрібно перевизначити метод accept():

    secondList.forEach(new Consumer<String>() {
       @Override
       public void accept(String s) {
           System.out.println(s);
       }
    });

    Висновок:

    
    Amigo
    Amigo
    Hello
    Hello

    Метод accept приймає як аргумент черговий елемент того типу, який зберігає ArrayList. Приклад для Integer:

    ArrayList<Integer> integerList = new ArrayList<>();
    integerList.forEach(new Consumer<Integer>() {
       @Override
       public void accept(Integer integer) {
           System.out.println(integer);
       }
    });

    Метод action()буде виконано кожного елемента.

  • get(int index)

    Повертає елемент, розташований у зазначеній позиції списку.

    Якщо index < 0або index >=максимальна кількість елементів списку, буде викинуто виняток IndexOutOfBoundsException.

    Це основний метод отримання елемента зі списку, час вилучення елемента індексу завжди буде однаковим, незалежно від розміру ArrayList.

  • indexOf(Object o)

    Метод повертає індекс першого входження елемента у списку. Якщо елемент не існує у списку, метод поверне -1.

  • isEmpty()

    Метод повертає true якщо список порожній, false у протилежному випадку.

    Якщо у списку містяться лише елементи null, метод поверне false . Іншими словами, nullелементи також враховуються цим способом.

  • iterator()

    Повертає ітератор для списку для подальшого використання в циклі або за будь-якої іншої обробки.

    Ітератор для ArrayList – fail-fast. Це означає, що якщо колекція зміниться під час ітерації, буде викинуто виняток ConcurrentModificationException. Детальніше про fail-fast та його протилежність fail-safe можна почитати тут .

  • lastIndexOf(Object o)

    Функціонал методу схожий на indexOf()відмінність в тому, що повертається індекс останнього елемента в списку.

    Якщо елемент не знайдено, він також повертає -1.

  • remove(int index)

    Видалення елемента у зазначеній позиції індексу. Після видалення зрушує всі елементи вліво для заповнення простору, що звільнився.

    Якщо index<0чи >=кількість елементів списку, буде викинуто виняток IndexOutOfBoundsException. В результаті метод повертає елемент, який було видалено.

  • remove(Object o)

    Метод видаляє зі списку переданий елемент o. Якщо елемент є у списку, він видаляється, а всі елементи зміщуються вліво. Якщо елемент існує у списку і успішно видалено, метод повертає true, інакше — false .

  • removeAll(Collection<?> c)

    Якщо необхідно видалити кілька елементів, не варто робити це в циклі за умовою: набагато зручніше та безпечніше скористатися методом removeAll(). Він приймає колекцію елементів, які будуть видалені зі списку.

    Колекція повинна містити елементи того ж типу, що зберігає цільовий список. У протилежному випадку буде викинуто ClassCastException. Метод поверне true , якщо список було змінено через виклик методу.

  • set(int index, E element)

    Заміна елемента у зазначеній позиції indexна переданий element. Індекс також повинен бути більшим за нуль і меншим за індекс останнього елемента, інакше буде викинуто виняток IndexOutOfBoundsException.

  • size()

    Найкращий спосіб (практично єдиний) для того, щоб дізнатися розмір масиву.

  • sort(Comparator<? super E> c)

    Сортування списку за заданим правилом. Правило сортування є реалізований інтерфейс Comparatorз перевизначеним методом compareTo().

    Перевизначення потрібне, якщо колекція містить об'єкти власного класу. При роботі зі стандартними класами ( Integer, Stringтощо) перевизначення compareTo()потрібне лише для нестандартного сортування.

  • toArray()

    Перетворює список на фіксований масив. Зауважте, що метод повертає масив об'єктів ( Object[]). Якщо необхідно привести список до масиву об'єктів певного типу, в якості параметра метод можна передати масив, куди будуть переміщені елементи списків.

    Приклад:

    String[] array = new String[secondList.size()];
    secondList.toArray(array);
    for(int i = 0; i< array.length; i++) {
       System.out.println(array[i]);
    }

    Висновок:

    
    Amigo
    Amigo
    Hello
    Hello
Методи ArrayList Java вивчаються на курсі JavaRush. Перше знайомство відбувається на сьомому рівні квесту Java Syntax, на лекції "Клас ArrayList" . На цьому ж рівні є добірки завдань – раз і два, в яких потрібно використовувати методи ArrayList, наведено додаткові приклади роботи з ArrayList та дженериками, а також пояснюється різниця між ArrayList та LinkedList. Це велика тема вивчення, тому в тому чи іншому вигляді до Arraylist в Java (методи цього класу - лише частина всього масиву знань, в який варто заглибитись) на курсі повертаються і на наступних рівнях навчання - Core, Collections, Multithreading. Ми віримо, що щоденна практика написання коду є головним ключем до успіху в програмуванні. Тому JavaRush на 80% складається з практичних завдань, міні-проектів, завдань-ігор. Все це — сотні годин кодингу, які допоможуть прокачати скіл.

Посилання на додаткове читання

  1. Детальна стаття про динамічні масиви , а точніше - про ArrayListта LinkedList, які виконують їхню роль у мові Java.
  2. Стаття про видалення елементів зі списку ArrayList .
  3. Лекція про роботу з ArrayList у схемах та картинках .
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ