1.6. Массивы
Материалы
Массив - это контейнер, который хранит фиксированное количество значений одного типа. Когда нужно работать с множеством связанных значений, массивы - ваш лучший друг!
Ваш первый массив
Представьте что вам нужно хранить температуры за неделю. Вместо создания семи отдельных переменных, используйте массив:
public class Main {
public static void main(String[] args) {
int[] temperatures = {18, 20, 22, 19, 21, 23, 20};
System.out.println("Понедельник: " + temperatures[0] + "°C");
System.out.println("Вторник: " + temperatures[1] + "°C");
}
}
Вывод:
Понедельник: 18°C
Вторник: 20°C
Индексация начинается с нуля! Первый элемент имеет индекс 0, второй - 1, и так далее.
Объявление массивов
Есть два способа объявить массив:
// Способ 1 (рекомендуемый)
int[] numbers;
String[] names;
// Способ 2 (не рекомендуется, но работает)
int numbers[];
String names[];
Первый способ более читаемый - квадратные скобки сразу показывают что это массив.
Примечание: Объявление массива не создаёт его, только говорит компилятору что переменная будет ссылаться на массив.
Создание массивов
Создание с помощью new
int[] numbers = new int[5]; // массив из 5 целых чисел
Это создаёт массив из 5 элементов, все инициализированы значением по умолчанию (0 для чисел):
[0, 0, 0, 0, 0]
Значения по умолчанию для разных типов:
- Числа (
int,double, и т.д.):0или0.0 boolean:false- Ссылочные типы:
null
Создание с инициализацией
Часто вы знаете значения заранее:
int[] scores = {95, 87, 92, 78, 88};
String[] colors = {"красный", "зелёный", "синий"};
Java автоматически определяет размер массива по количеству элементов.
Работа с элементами
Доступ к элементам
Используйте квадратные скобки и индекс:
int[] numbers = {10, 20, 30, 40, 50};
System.out.println(numbers[0]); // 10
System.out.println(numbers[2]); // 30
System.out.println(numbers[4]); // 50
Изменение элементов
int[] numbers = {10, 20, 30};
numbers[1] = 99; // изменяем второй элемент
System.out.println(numbers[1]); // 99
Длина массива
Каждый массив знает свою длину:
int[] numbers = {10, 20, 30, 40, 50};
System.out.println("Длина массива: " + numbers.length); // 5
Важно:
length- это свойство, а не метод! Без скобок.
Перебор массивов
С помощью обычного for
int[] numbers = {10, 20, 30, 40, 50};
for (int i = 0; i < numbers.length; i++) {
System.out.println("Элемент " + i + ": " + numbers[i]);
}
Вывод:
Элемент 0: 10
Элемент 1: 20
Элемент 2: 30
Элемент 3: 40
Элемент 4: 50
С помощью enhanced for (for-each)
Когда индекс не нужен, используйте более простую форму:
int[] numbers = {10, 20, 30, 40, 50};
for (int num : numbers) {
System.out.println(num);
}
Это читается как “для каждого num в numbers”. Намного проще!
Вычисление суммы
int[] scores = {95, 87, 92, 78, 88};
int sum = 0;
for (int score : scores) {
sum += score;
}
double average = sum / (double) scores.length;
System.out.println("Средний балл: " + average);
Вывод:
Средний балл: 88.0
Многомерные массивы
Массив может содержать другие массивы! Это полезно для матриц и таблиц.
Двумерный массив (матрица)
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println(matrix[0][0]); // 1
System.out.println(matrix[1][2]); // 6
System.out.println(matrix[2][1]); // 8
Визуализация:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Создание многомерного массива
// Прямоугольный массив 3x4
int[][] table = new int[3][4];
// "Рваный" массив - строки разной длины
int[][] ragged = {
{1, 2},
{3, 4, 5},
{6}
};
Перебор двумерного массива
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println(); // новая строка
}
Вывод:
1 2 3
4 5 6
7 8 9
С enhanced for:
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
Копирование массивов
Почему простое присваивание не работает
int[] original = {1, 2, 3};
int[] copy = original; // ЭТО НЕ КОПИЯ!
copy[0] = 999;
System.out.println(original[0]); // 999 - упс!
Переменные массивов хранят ссылки, а не сами данные. Обе переменные указывают на один массив!
Копирование с помощью цикла
int[] original = {1, 2, 3, 4, 5};
int[] copy = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i];
}
Работает, но многословно.
Использование System.arraycopy()
int[] original = {1, 2, 3, 4, 5};
int[] copy = new int[original.length];
System.arraycopy(original, 0, copy, 0, original.length);
// System.arraycopy(источник, откуда, назначение, куда, сколько)
Можно копировать часть массива:
String[] coffees = {
"Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",
"Doppio", "Espresso", "Frappucino", "Freddo"
};
String[] selection = new String[4];
System.arraycopy(coffees, 2, selection, 0, 4);
for (String coffee : selection) {
System.out.print(coffee + " ");
}
Вывод:
Cappuccino Corretto Cortado Doppio
Использование Arrays.copyOf()
Самый простой способ:
import java.util.Arrays;
int[] original = {1, 2, 3, 4, 5};
int[] copy = Arrays.copyOf(original, original.length);
Можно изменить размер:
int[] bigger = Arrays.copyOf(original, 10); // новые элементы = 0
int[] smaller = Arrays.copyOf(original, 3); // только первые 3
Использование Arrays.copyOfRange()
Копирование части массива:
import java.util.Arrays;
String[] coffees = {
"Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",
"Doppio", "Espresso", "Frappucino", "Freddo"
};
String[] selection = Arrays.copyOfRange(coffees, 2, 6);
// От индекса 2 (включительно) до 6 (не включая)
for (String coffee : selection) {
System.out.print(coffee + " ");
}
Вывод:
Cappuccino Corretto Cortado Doppio
Полезные методы класса Arrays
Класс java.util.Arrays содержит множество полезных методов для работы с массивами.
Сортировка
import java.util.Arrays;
int[] numbers = {5, 2, 8, 1, 9};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));
Вывод:
[1, 2, 5, 8, 9]
Работает и со строками:
String[] names = {"Зина", "Алиса", "Боб"};
Arrays.sort(names);
System.out.println(Arrays.toString(names));
Вывод:
[Алиса, Боб, Зина]
Бинарный поиск
Быстрый поиск в отсортированном массиве:
import java.util.Arrays;
int[] numbers = {1, 3, 5, 7, 9, 11};
int index = Arrays.binarySearch(numbers, 7);
System.out.println("Число 7 находится на индексе: " + index); // 3
Важно: Массив должен быть отсортирован! Иначе результат непредсказуем.
Если элемент не найден, возвращается отрицательное число:
int notFound = Arrays.binarySearch(numbers, 4);
System.out.println(notFound); // -3 (отрицательное)
Заполнение массива
import java.util.Arrays;
int[] numbers = new int[5];
Arrays.fill(numbers, 42);
System.out.println(Arrays.toString(numbers));
Вывод:
[42, 42, 42, 42, 42]
Можно заполнить часть массива:
int[] numbers = new int[10];
Arrays.fill(numbers, 2, 7, 99); // от индекса 2 до 7
System.out.println(Arrays.toString(numbers));
Вывод:
[0, 0, 99, 99, 99, 99, 99, 0, 0, 0]
Сравнение массивов
import java.util.Arrays;
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = {1, 2, 4};
System.out.println(Arrays.equals(array1, array2)); // true
System.out.println(Arrays.equals(array1, array3)); // false
Внимание: Оператор
==сравнивает ссылки, не содержимое!
System.out.println(array1 == array2); // false (разные объекты)
System.out.println(Arrays.equals(array1, array2)); // true (одинаковое содержимое)
Преобразование в строку
import java.util.Arrays;
int[] numbers = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(numbers));
Вывод:
[1, 2, 3, 4, 5]
Для многомерных массивов используйте deepToString():
int[][] matrix = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(matrix));
Вывод:
[[1, 2], [3, 4]]
Создание списка из массива
import java.util.Arrays;
import java.util.List;
String[] array = {"Яблоко", "Банан", "Апельсин"};
List<String> list = Arrays.asList(array);
System.out.println(list);
Вывод:
[Яблоко, Банан, Апельсин]
Примечание: Полученный список имеет фиксированный размер - нельзя добавлять или удалять элементы!
Частые ошибки и их решение
ArrayIndexOutOfBoundsException
Самая частая ошибка при работе с массивами:
int[] numbers = {10, 20, 30};
System.out.println(numbers[5]); // Ошибка! Индекс вне границ
Всегда проверяйте границы:
int index = 5;
if (index >= 0 && index < numbers.length) {
System.out.println(numbers[index]);
} else {
System.out.println("Индекс вне границ!");
}
NullPointerException
int[] numbers = null;
System.out.println(numbers.length); // Ошибка! numbers это null
Проверяйте на null:
if (numbers != null) {
System.out.println(numbers.length);
} else {
System.out.println("Массив не инициализирован!");
}
Изменение размера массива
Размер массива фиксирован после создания! Нельзя:
int[] numbers = {1, 2, 3};
numbers.length = 5; // ОШИБКА КОМПИЛЯЦИИ!
Решение - создать новый массив:
int[] numbers = {1, 2, 3};
int[] bigger = Arrays.copyOf(numbers, 5);
Или используйте ArrayList для динамического размера:
import java.util.ArrayList;
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4); // можно добавлять сколько угодно!
Практические примеры
Поиск максимального элемента
int[] numbers = {23, 45, 12, 67, 34, 89, 15};
int max = numbers[0];
for (int num : numbers) {
if (num > max) {
max = num;
}
}
System.out.println("Максимум: " + max); // 89
Реверс массива
int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length / 2; i++) {
int temp = numbers[i];
numbers[i] = numbers[numbers.length - 1 - i];
numbers[numbers.length - 1 - i] = temp;
}
System.out.println(Arrays.toString(numbers));
Вывод:
[5, 4, 3, 2, 1]
Удаление дубликатов
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
int[] numbers = {1, 2, 3, 2, 4, 3, 5};
Set<Integer> set = new HashSet<>();
for (int num : numbers) {
set.add(num);
}
int[] unique = new int[set.size()];
int i = 0;
for (int num : set) {
unique[i++] = num;
}
Arrays.sort(unique);
System.out.println(Arrays.toString(unique));
Вывод:
[1, 2, 3, 4, 5]
Сдвиг элементов
int[] numbers = {1, 2, 3, 4, 5};
// Сдвиг вправо
int last = numbers[numbers.length - 1];
for (int i = numbers.length - 1; i > 0; i--) {
numbers[i] = numbers[i - 1];
}
numbers[0] = last;
System.out.println(Arrays.toString(numbers));
Вывод:
[5, 1, 2, 3, 4]
Лучшие практики
Используйте константы для размеров
// Плохо
int[] scores = new int[100];
// Хорошо
final int MAX_STUDENTS = 100;
int[] scores = new int[MAX_STUDENTS];
Проверяйте границы
public static int getElement(int[] array, int index) {
if (array == null) {
throw new IllegalArgumentException("Массив null");
}
if (index < 0 || index >= array.length) {
throw new IndexOutOfBoundsException("Индекс: " + index);
}
return array[index];
}
Используйте enhanced for когда возможно
// Хорошо для чтения
for (int num : numbers) {
System.out.println(num);
}
// Используйте обычный for когда нужен индекс
for (int i = 0; i < numbers.length; i++) {
System.out.println("Индекс " + i + ": " + numbers[i]);
}
Предпочитайте Collections для сложной логики
Для динамических коллекций используйте ArrayList:
// Вместо
int[] numbers = new int[10];
int count = 0;
// Используйте
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(42); // проще!
Итоги
Вы изучили массивы в Java:
- Объявление и создание массивов
- Доступ и изменение элементов
- Перебор массивов циклами
- Многомерные массивы
- Копирование массивов
- Полезные методы
Arrays - Частые ошибки и как их избежать
- Практические примеры
Массивы - фундаментальная структура данных. Они быстрые и эффективные, но помните:
- Размер фиксирован после создания
- Индексация начинается с 0
- Всегда проверяйте границы
Для динамических коллекций рассмотрите использование ArrayList и других классов из пакета java.util.
Задания для практики
Попробуйте написать программы для:
- Нахождения второго по величине элемента в массиве
- Проверки является ли массив палиндромом
- Слияния двух отсортированных массивов в один отсортированный
- Подсчёта частоты каждого элемента в массиве
Удачи!