☕ Java

Методы массивов и коллекций в Java: подробное руководство

Что это такое и зачем? (аналогия из реальной жизни)

Представь, что ты — учитель физкультуры, и у тебя есть список учеников в классе. Этот список — массив или коллекция (список) имён. Без методов тебе пришлось бы делать всё вручную: переписывать список от руки, если кто-то заболел, искать глазами фамилию ученика, считать, сколько всего человек в классе. Это долго и неудобно.

Методы массивов и коллекций — это как набор волшебных инструментов, которые делают всю рутинную работу за тебя. Хочешь узнать, есть ли в списке ученик Петров? Просто вызови метод contains("Петров"). Нужно отсортировать всех по алфавиту? Используй sort(). Хочешь добавить новенького? Напиши add("Новичок").

В реальной жизни мы постоянно работаем со списками: список покупок, плейлист в телефоне, контакты в записной книжке. Программы тоже постоянно работают с наборами данных. Методы — это готовые команды, которые экономят время и силы программиста, позволяя не изобретать велосипед каждый раз, когда нужно что-то сделать со списком.

💡 Важно: Массивы в Java — это базовые структуры, а коллекции (например, ArrayList) — это более продвинутые и удобные "контейнеры" для хранения данных. Методы есть и у тех, и у других, но у коллекций их гораздо больше.

Теория: как это работает изнутри

Давай заглянем "под капот". Когда ты создаёшь массив в Java, ты выделяешь в памяти компьютера непрерывную цепочку ячеек. Каждая ячейка хранит одно значение (число, строку, объект). У каждой ячейки есть номер — индекс. Первая ячейка имеет индекс 0, вторая — 1 и так далее.

Методы массивов — это встроенные функции, которые умеют ходить по этим ячейкам и что-то с ними делать. Например, метод Arrays.sort() переставляет значения в ячейках так, чтобы они шли по возрастанию. Он не создаёт новый массив, а меняет порядок в том же самом.

Коллекции (например, ArrayList) работают хитрее. Внутри у них тоже есть массив, но он "резиновый". Когда ты добавляешь новый элемент, а места в массиве уже нет, коллекция автоматически создаёт новый массив большего размера, копирует туда все старые элементы и добавляет новый. Старый массив удаляется. Этот процесс называется динамическим расширением.

Методы коллекций делятся на несколько групп:

  • Добавление: add(), addAll()
  • Удаление: remove(), clear()
  • Поиск: contains(), indexOf()
  • Изменение: set(), sort()
  • Информация: size(), isEmpty()

Каждый метод — это маленькая программа, которая выполняет одну конкретную задачу. Например, метод contains() проходит по всем элементам коллекции и сравнивает каждый с тем, что ты ищешь. Если находит совпадение — возвращает true, если нет — false.

⚠️ Запомни: У массивов фиксированная длина. Если ты создал массив на 10 элементов, ты не сможешь добавить 11-й. Коллекции (ArrayList) могут расти и сжиматься автоматически.

Синтаксис в Java: все формы и варианты

Давай разберём синтаксис на примере двух самых популярных структур: массива и ArrayList.

1. Массивы (класс Arrays)

Для работы с методами массивов нужно импортировать java.util.Arrays.

Метод Что делает Пример
sort(массив) Сортирует массив по возрастанию Arrays.sort(arr);
toString(массив) Превращает массив в строку для вывода Arrays.toString(arr)
binarySearch(массив, ключ) Ищет элемент в отсортированном массиве Arrays.binarySearch(arr, 5)
fill(массив, значение) Заполняет весь массив одним значением Arrays.fill(arr, 0);
copyOf(массив, длина) Копирует массив (можно обрезать или расширить) Arrays.copyOf(arr, 10)
equals(массив1, массив2) Сравнивает два массива поэлементно Arrays.equals(a, b)

2. Коллекции (ArrayList)

Для работы с ArrayList нужно импортировать java.util.ArrayList и java.util.Collections (для дополнительных методов).

Метод Что делает Пример
add(элемент) Добавляет элемент в конец списка list.add("Привет");
add(индекс, элемент) Добавляет элемент на указанную позицию list.add(0, "Первый");
get(индекс) Возвращает элемент по индексу String s = list.get(2);
set(индекс, элемент) Заменяет элемент на указанной позиции list.set(1, "Новый");
remove(индекс) Удаляет элемент по индексу list.remove(0);
remove(объект) Удаляет первое вхождение объекта list.remove("Вася");
size() Возвращает количество элементов int n = list.size();
contains(объект) Проверяет, есть ли элемент в списке boolean b = list.contains("Маша");
indexOf(объект) Возвращает индекс первого вхождения int i = list.indexOf("Петя");
isEmpty() Проверяет, пуст ли список boolean empty = list.isEmpty();
clear() Очищает список (удаляет все элементы) list.clear();
toArray() Превращает список в массив Object[] arr = list.toArray();

3. Дополнительные методы из Collections

Метод Что делает Пример
sort(список) Сортирует список Collections.sort(list);
reverse(список) Переворачивает список задом наперёд Collections.reverse(list);
shuffle(список) Перемешивает элементы случайным образом Collections.shuffle(list);
max(список) Находит максимальный элемент String max = Collections.max(list);
min(список) Находит минимальный элемент String min = Collections.min(list);
frequency(список, объект) Считает, сколько раз встречается объект int count = Collections.frequency(list, "Аня");

Примеры кода — от простого к сложному

Пример 1: Базовые операции с массивом

import java.util.Arrays; // Импортируем класс Arrays для работы с массивами

public class ArrayExample1 {
    public static void main(String[] args) {
        // Создаём массив чисел
        int[] numbers = {5, 2, 8, 1, 9};
        
        // Выводим массив на экран (без метода toString увидим мусор)
        System.out.println("Исходный массив: " + Arrays.toString(numbers));
        // Вывод: Исходный массив: [5, 2, 8, 1, 9]
        
        // Сортируем массив по возрастанию
        Arrays.sort(numbers);
        System.out.println("После сортировки: " + Arrays.toString(numbers));
        // Вывод: После сортировки: [1, 2, 5, 8, 9]
        
        // Ищем число 5 в отсортированном массиве
        int index = Arrays.binarySearch(numbers, 5);
        System.out.println("Индекс числа 5: " + index);
        // Вывод: Индекс числа 5: 2 (потому что после сортировки 5 стоит на 2-й позиции)
        
        // Заполняем массив нулями
        Arrays.fill(numbers, 0);
        System.out.println("После fill: " + Arrays.toString(numbers));
        // Вывод: После fill: [0, 0, 0, 0, 0]
    }
}

Пример 2: Создание и работа с ArrayList

import java.util.ArrayList; // Импортируем ArrayList

public class ArrayListExample2 {
    public static void main(String[] args) {
        // Создаём список строк
        ArrayList<String> fruits = new ArrayList<>();
        
        // Добавляем элементы
        fruits.add("Яблоко");
        fruits.add("Банан");
        fruits.add("Апельсин");
        fruits.add("Киви");
        
        System.out.println("Список фруктов: " + fruits);
        // Вывод: Список фруктов: [Яблоко, Банан, Апельсин, Киви]
        
        // Получаем элемент по индексу
        String secondFruit = fruits.get(1); // Индекс 1 — это второй элемент
        System.out.println("Второй фрукт: " + secondFruit);
        // Вывод: Второй фрукт: Банан
        
        // Удаляем элемент по индексу
        fruits.remove(0); // Удаляем "Яблоко"
        System.out.println("После удаления первого: " + fruits);
        // Вывод: После удаления первого: [Банан, Апельсин, Киви]
        
        // Проверяем, есть ли в списке "Киви"
        boolean hasKiwi = fruits.contains("Киви");
        System.out.println("Есть ли Киви? " + hasKiwi);
        // Вывод: Есть ли Киви? true
        
        // Узнаём размер списка
        System.out.println("Размер списка: " + fruits.size());
        // Вывод: Размер списка: 3
    }
}

Пример 3: Добавление и вставка в середину

import java.util.ArrayList;

public class ArrayListExample3 {
    public static void main(String[] args) {
        ArrayList<String> students = new ArrayList<>();
        
        // Добавляем учеников
        students.add("Аня");
        students.add("Петя");
        students.add("Маша");
        
        System.out.println("Исходный список: " + students);
        // Вывод: Исходный список: [Аня, Петя, Маша]
        
        // Вставляем "Вася" на позицию 1 (между Аней и Петей)
        students.add(1, "Вася");
        System.out.println("После вставки Васи: " + students);
        // Вывод: После вставки Васи: [Аня, Вася, Петя, Маша]
        
        // Заменяем элемент на позиции 2 (Петю) на "Коля"
        students.set(2, "Коля");
        System.out.println("После замены: " + students);
        // Вывод: После замены: [Аня, Вася, Коля, Маша]
    }
}

Пример 4: Сортировка и переворот списка

import java.util.ArrayList;
import java.util.Collections; // Импортируем Collections для дополнительных методов

public class ArrayListExample4 {
    public static void main(String[] args) {
        ArrayList<Integer> scores = new ArrayList<>();
        scores.add(85);
        scores.add(92);
        scores.add(78);
        scores.add(95);
        scores.add(88);
        
        System.out.println("Исходные баллы: " + scores);
        // Вывод: Исходные баллы: [85, 92, 78, 95, 88]
        
        // Сортируем по возрастанию
        Collections.sort(scores);
        System.out.println("После сортировки: " + scores);
        // Вывод: После сортировки: [78, 85, 88, 92, 95]
        
        // Переворачиваем список (теперь по убыванию)
        Collections.reverse(scores);
        System.out.println("После переворота: " + scores);
        // Вывод: После переворота: [95, 92, 88, 85, 78]
        
        // Находим максимальный и минимальный баллы
        int maxScore = Collections.max(scores);
        int minScore = Collections.min(scores);
        System.out.println("Максимум: " + maxScore + ", Минимум: " + minScore);
        // Вывод: Максимум: 95, Минимум: 78
    }
}

Пример 5: Подсчёт частоты элементов

import java.util.ArrayList;
import java.util.Collections;

public class ArrayListExample5 {
    public static void main(String[] args) {
        ArrayList<String> votes = new ArrayList<>();
        votes.add("Кошка");
        votes.add("Собака");
        votes.add("Кошка");
        votes.add("Попугай");
        votes.add("Кошка");
        votes.add("Собака");
        
        System.out.println("Голоса: " + votes);
        // Вывод: Голоса: [Кошка, Собака, Кошка, Попугай, Кошка, Собака]
        
        // Считаем, сколько раз встречается "Кошка"
        int catCount = Collections.frequency(votes, "Кошка");
        System.out.println("Кошка встречается " + catCount + " раз(а)");
        // Вывод: Кошка встречается 3 раз(а)
        
        // Считаем, сколько раз встречается "Собака"
        int dogCount = Collections.frequency(votes, "Собака");
        System.out.println("Собака встречается " + dogCount + " раз(а)");
        // Вывод: Собака встречается 2 раз(а)
    }
}

Пример 6: Превращение массива в список и обратно

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ArrayToListExample6 {
    public static void main(String[] args) {
        // У нас есть массив
        String[] colorsArray = {"Красный", "Зелёный", "Синий", "Жёлтый"};
        System.out.println("Массив: " + Arrays.toString(colorsArray));
        // Вывод: Массив: [Красный, Зелёный, Синий, Жёлтый]
        
        // Превращаем массив в список (но этот список фиксированного размера!)
        List<String> colorsList = Arrays.asList(colorsArray);
        System.out.println("Список из массива: " + colorsList);
        // Вывод: Список из массива: [Красный, Зелёный, Синий, Жёлтый]
        
        // Чтобы получить полноценный ArrayList, создаём новый
        ArrayList<String> fullList = new ArrayList<>(colorsList);
        fullList.add("Фиолетовый"); // Теперь можно добавлять
        System.out.println("Полноценный список: " + fullList);
        // Вывод: Полноценный список: [Красный, Зелёный, Синий, Жёлтый, Фиолетовый]
        
        // Превращаем ArrayList обратно в массив
        String[] newArray = fullList.toArray(new String[0]);
        System.out.println("Новый массив: " + Arrays.toString(newArray));
        // Вывод: Новый массив: [Красный, Зелёный, Синий, Жёлтый, Фиолетовый]
    }
}

Пример 7: Сложный пример — работа с числами и статистика

import java.util.ArrayList;
import java.util.Collections;

public class ComplexExample7 {
    public static void main(String[] args) {
        // Создаём список температур за неделю
        ArrayList<Double> temperatures = new ArrayList<>();
        temperatures.add(23.5);
        temperatures.add(25.0);
        temperatures.add(19.8);
        temperatures.add(22.1);
        temperatures.add(26.3);
        temperatures.add(21.7);
        temperatures.add(24.9);
        
        System.out.println("Температуры за неделю: " + temperatures);
        
        // Сортируем
        Collections.sort(temperatures);
        System.out.println("Отсортированные: " + temperatures);
        
        // Находим среднюю температуру
        double sum = 0;
        for (double temp : temperatures) {
            sum += temp; // Суммируем все температуры
        }
        double average = sum / temperatures.size();
        System.out.println("Средняя температура: " + average);
        
        // Находим медиану (средний элемент в отсортированном списке)
        int middle = temperatures.size() / 2; // 7 / 2 = 3 (индекс 3 — это 4-й элемент)
        double median = temperatures.get(middle);
        System.out.println("Медиана: " + median);
        
        // Проверяем, была ли температура выше 30 градусов
        boolean hasHotDay = false;
        for (double temp : temperatures) {
            if (temp > 30) {
                hasHotDay = true;
                break; // Если нашли, выходим из цикла
            }
        }
        System.out.println("Был ли жаркий день (>30)? " + hasHotDay);
        // Вывод: Был ли жаркий день (>30)? false
        
        // Удаляем самую низкую и самую высокую температуру
        temperatures.remove(0); // Самая низкая (после сортировки — первый элемент)
        temperatures.remove(temperatures.size() - 1); // Самая высокая (последний элемент)
        System.out.println("После удаления крайних: " + temperatures);
    }
}

Сравнение с Python: чем похоже и чем отличается

Если ты уже знаком с Python, тебе будет проще понять Java. Давай сравним основные операции.

Операция Java (ArrayList) Python (list)
Создание списка ArrayList<String> list = new ArrayList<>(); list = []
Добавление элемента list.add("Привет"); list.append("Привет")
Получение по индексу list.get(0); list[0]
Изменение по индексу list.set(0, "Новый"); list[0] = "Новый"
Длина списка list.size(); len(list)
Проверка наличия list.contains("Кот"); "Кот" in list
Удаление по значению list.remove("Кот"); list.remove("Кот")
Удаление по индексу list.remove(0); del list[0]
Сортировка Collections.sort(list); list.sort()
Переворот Collections.reverse(list); list.reverse()
Очистка list.clear(); list.clear()

Главные отличия:

  • Типизация: В Java нужно указывать тип элементов (через угловые скобки <String>). В Python типы не указываются.
  • Синтаксис: В Java методы вызываются через точку, но с круглыми скобками и точкой с запятой. В Python синтаксис короче и проще.
  • Производительность: Java обычно быстрее, но требует больше кода.
  • Массивы: В Java есть отдельные массивы (фиксированной длины) и коллекции. В Python списки — это единственный тип "массива" (динамический).
💡 Совет: Если ты переходишь с Python на Java, запомни главное правило: в Java почти всё нужно делать через методы, а не через операторы. Вместо list[0] пиши list.get(0), вместо len(list) — list.size().

Типичные ошибки и подводные камни

Ошибка 1: Выход за границы массива

int[] arr = {1, 2, 3};
System.out.println(arr[3]); // Ошибка! Индекс 3 не существует (массив от 0 до 2)
// Java выбросит исключение ArrayIndexOutOfBoundsException

Как избежать: Всегда проверяй, что индекс меньше длины массива (arr.length).

Ошибка 2: Забыл импортировать класс

// Забыли написать: import java.util.ArrayList;
ArrayList<String> list = new ArrayList<>(); // Ошибка компиляции!

Как избежать: IDE (среда разработки) обычно сама предлагает импорт. Научись пользоваться автодополнением.

Ошибка 3: Использование Arrays.asList() как полноценного ArrayList

List<String> list = Arrays.asList("A", "B", "C");
list.add("D"); // Ошибка! Этот список фиксированного размера

Как избежать: Если нужен изменяемый список, создавай новый ArrayList на основе Arrays.asList().

Ошибка 4: Путаница между remove(int) и remove(Object)

ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.remove(1); // Удалит элемент с индексом 1 (число 2), а не число 1!

Как избежать: Если хочешь удалить число 1, используй numbers.remove(Integer.valueOf(1)).

Ошибка 5: Изменение списка во время обхода

ArrayList<String> names = new ArrayList<>();
names.add("Аня");
names.add("Петя");
names.add("Маша");

for (String name : names) {
    if (name.equals("Петя")) {
        names.remove(name); // Ошибка! ConcurrentModificationException
    }
}

Как избежать: Используй итератор (Iterator) или собирай элементы для удаления в отдельный список.

Ошибка 6: Сравнение строк через ==

ArrayList<String> list = new ArrayList<>();
list.add("Привет");
if (list.get(0) == "Привет") { // Неправильно! Сравниваются ссылки, а не значения
    // Этот код может не сработать
}

Как избежать: Всегда используй equals() для сравнения строк: list.get(0).equals("Привет").

Лучшие практики и советы профессионалов

  1. Используй ArrayList вместо массивов, если не уверен. Массивы хороши, когда знаешь точное количество элементов. Во всех остальных случаях ArrayList удобнее.
  2. Инициализируй ArrayList с указанием ёмкости. Если знаешь, что будет много элементов, укажи начальную ёмкость: new ArrayList<>(100). Это ускорит работу.
  3. Не бойся методов из Collections. Collections.sort(), Collections.reverse(), Collections.shuffle() — твои лучшие друзья. Не пиши свои велосипеды.
  4. Используй foreach для чтения. Цикл for (String s : list) безопаснее и читается лучше, чем обычный for с индексом.
  5. Проверяй на null. Перед вызовом методов убедись, что список не равен null. Иначе получишь NullPointerException.
  6. Используй generics (угловые скобки). Всегда указывай тип: ArrayList<String>, а не просто ArrayList. Это защитит от ошибок.
  7. Для поиска используй binarySearch только на отсортированных массивах. Иначе результат будет непредсказуем.
  8. Копируй массивы через copyOf, а не вручную. Это быстрее и надёжнее.
🔥 Золотое правило: "Не изобретай велосипед". Прежде чем писать свою реализацию поиска, сортировки или копирования, посмотри, нет ли готового метода в Java. Скорее всего, он есть и работает лучше.

Вопросы для самопроверки

  1. Вопрос: Какая разница между массивом и ArrayList?

    Ответ: Массив имеет фиксированную длину, ArrayList может динамически расширяться. У ArrayList больше методов для работы (add, remove, contains и т.д.).

  2. Вопрос: Какой метод нужно вызвать, чтобы узнать количество элементов в ArrayList?

    Ответ: Метод size(). Например: list.size().

  3. Вопрос: Что делает метод Arrays.toString()?

    Ответ: Превращает массив в строку вида [элемент1, элемент2, ...]