☕ Java
Arrays (Listen) in Java 17: Ausführliches Handbuch
Коллекции Java: ArrayList, HashMap и HashSet для начинающих
Массивы хороши, но их размер фиксирован при создании. В реальных программах данных бывает разное количество: список заказов, результаты поиска, контакты в телефоне. Для этого в Java есть коллекции — гибкие структуры данных с автоматическим изменением размера.
Иерархия коллекций Java (JCF)
java.util — пакет с коллекциями
├── List (упорядоченные, разрешены дубликаты)
│ ├── ArrayList — быстрый доступ по индексу
│ └── LinkedList — быстрые вставки/удаления
│
├── Set (без дубликатов)
│ ├── HashSet — быстрый, без порядка
│ └── TreeSet — отсортированный
│
└── Map (пары ключ=значение)
├── HashMap — быстрый, без порядка
└── TreeMap — отсортированный по ключу
ArrayList vs Массив
import java.util.*;
// МАССИВ — фиксированный размер
String[] arr = new String[3];
arr[0]="яблоко"; arr[1]="груша"; arr[2]="банан";
// arr[3]="манго"; // ArrayIndexOutOfBoundsException!
// ARRAYLIST — размер растёт автоматически
ArrayList list = new ArrayList<>();
list.add("яблоко");
list.add("груша");
list.add("банан");
list.add("манго"); // Легко! Размер автоматически увеличится
list.add("апельсин");
System.out.println(list); // [яблоко, груша, банан, манго, апельсин]
System.out.println(list.size()); // 5 (не length!)
System.out.println(list.get(0)); // яблоко
System.out.println(list.get(list.size()-1)); // апельсин (последний)
ArrayList: полный арсенал операций
import java.util.*;
public class ArrayListOps {
public static void main(String[] args) {
ArrayList nums = new ArrayList<>();
// Добавление
for (int n : new int[]{5,2,8,1,9,3,7}) nums.add(n);
System.out.println("Исходный: " + nums);
// Вставка по позиции (сдвигает остальные)
nums.add(2, 100); // вставить 100 на позицию 2
System.out.println("После add(2,100): " + nums);
// Замена
nums.set(0, 50);
System.out.println("После set(0,50): " + nums);
// Удаление по значению
nums.remove(Integer.valueOf(100)); // Удалить значение 100
// Удаление по индексу
nums.remove(0); // Удалить элемент с индексом 0
System.out.println("После удалений: " + nums);
// Поиск
System.out.println("Есть 8? " + nums.contains(8));
System.out.println("Индекс 9: " + nums.indexOf(9));
// Сортировка
Collections.sort(nums);
System.out.println("Отсортированный: " + nums);
Collections.sort(nums, Collections.reverseOrder());
System.out.println("Обратный: " + nums);
// Статистика
System.out.println("Max: " + Collections.max(nums));
System.out.println("Min: " + Collections.min(nums));
// Перемешать
Collections.shuffle(nums);
System.out.println("Перемешанный: " + nums);
// Очистить
nums.clear();
System.out.println("Пустой? " + nums.isEmpty()); // true
// Создать из массива
List fruits = new ArrayList<>(Arrays.asList("яблоко","груша","банан"));
System.out.println(fruits);
}
}
LinkedList: когда вставки важнее доступа
import java.util.LinkedList;
LinkedList list = new LinkedList<>();
// Добавление в начало/конец
list.addFirst("Иван"); // Начало
list.addLast("Мария"); // Конец
list.addFirst("Боб"); // Начало → [Боб, Иван, Мария]
System.out.println(list.getFirst()); // Боб
System.out.println(list.getLast()); // Мария
// Удаление
String f = list.removeFirst(); // "Боб" (очередь FIFO)
String l = list.removeLast(); // "Мария"
System.out.println(list); // [Иван]
// LinkedList как стек (LIFO: последним вошёл — первым вышел)
LinkedList stack = new LinkedList<>();
stack.push("A"); stack.push("B"); stack.push("C");
System.out.println(stack.pop()); // C (последний вошёл — первый вышел)
System.out.println(stack.pop()); // B
// Когда использовать?
// ArrayList: быстрый доступ по индексу get(i) — O(1)
// LinkedList: быстрые вставки в начало/конец — O(1), но медленный get — O(n)
HashMap: телефонная книга
Аналогия: Телефонная книга. Ищете по имени (ключ) — получаете номер (значение). Мгновенно!
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
HashMap capitals = new HashMap<>();
// put(ключ, значение)
capitals.put("Россия", "Москва");
capitals.put("Франция", "Париж");
capitals.put("Германия","Берлин");
capitals.put("Япония", "Токио");
// get(ключ) → значение
System.out.println("Столица Франции: " + capitals.get("Франция")); // Париж
System.out.println("Столица Италии: " + capitals.get("Италия")); // null (нет ключа)
// getOrDefault — значение по умолчанию если ключ не найден
System.out.println(capitals.getOrDefault("Италия", "Неизвестно")); // Неизвестно
// Проверка наличия
System.out.println("Есть Япония? " + capitals.containsKey("Япония")); // true
System.out.println("Есть Токио? " + capitals.containsValue("Токио")); // true
// Обновление (put перезаписывает)
capitals.put("Германия", "Берлин (Berlin)");
// Удаление
capitals.remove("Франция");
System.out.println("После удаления: " + capitals.size()); // 3
// Перебор всех пар
System.out.println("Все столицы:");
for (Map.Entry e : capitals.entrySet()) {
System.out.println(" " + e.getKey() + " → " + e.getValue());
}
// Перебор ключей
for (String country : capitals.keySet())
System.out.println(country);
// Перебор значений
for (String capital : capitals.values())
System.out.println(capital);
// Практика: подсчёт частоты слов
String text = "java python java java python c++ java";
HashMap freq = new HashMap<>();
for (String word : text.split(" ")) {
freq.put(word, freq.getOrDefault(word, 0) + 1);
}
System.out.println("Частота: " + freq); // {java=4, python=2, c++=1}
// Сортировка по значению
freq.entrySet().stream()
.sorted(Map.Entry.comparingByValue().reversed())
.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
}
}
HashSet: только уникальные элементы
Аналогия: Ящик для уникальных предметов. Положите два одинаковых — останется один. Удобно для хранения уникальных значений и проверки принадлежности.
import java.util.*;
HashSet cities = new HashSet<>();
cities.add("Москва"); cities.add("Питер");
cities.add("Новосибирск"); cities.add("Москва"); // Дубликат — игнорируется!
System.out.println("Городов: " + cities.size()); // 3 (не 4!)
System.out.println(cities); // [Питер, Новосибирск, Москва] (порядок произвольный)
// contains — O(1)! Мгновенная проверка
System.out.println("Москва есть? " + cities.contains("Москва")); // true
System.out.println("Лондон есть? " + cities.contains("Лондон")); // false
// Операции над множествами
HashSet a = new HashSet<>(Arrays.asList(1,2,3,4,5));
HashSet b = new HashSet<>(Arrays.asList(3,4,5,6,7));
// Пересечение
HashSet inter = new HashSet<>(a);
inter.retainAll(b);
System.out.println("Пересечение: " + inter); // [3,4,5]
// Объединение
HashSet union = new HashSet<>(a);
union.addAll(b);
System.out.println("Объединение: " + union); // [1,2,3,4,5,6,7]
// Разность
HashSet diff = new HashSet<>(a);
diff.removeAll(b);
System.out.println("Разность a-b: " + diff); // [1,2]
// Практика: найти уникальные слова
String text = "java python java go python java";
HashSet unique = new HashSet<>(Arrays.asList(text.split(" ")));
System.out.println("Уникальных языков: " + unique.size()); // 3
System.out.println(unique); // [go, java, python]
Iterator: безопасный обход с удалением
import java.util.*;
ArrayList nums = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
// Нельзя удалять элементы в for-each — ConcurrentModificationException!
// for (int n : nums) { if(n%2==0) nums.remove(Integer.valueOf(n)); } // ОШИБКА!
// Правильно: используйте Iterator
Iterator it = nums.iterator();
while (it.hasNext()) {
int n = it.next();
if (n % 2 == 0) it.remove(); // Безопасное удаление
}
System.out.println("Нечётные: " + nums); // [1,3,5,7,9]
// Элегантнее (Java 8+): removeIf
ArrayList names = new ArrayList<>(Arrays.asList("Иван","Ал","Мария","Б","Алексей"));
names.removeIf(name -> name.length() < 4); // Удалить короткие имена
System.out.println(names); // [Иван, Мария, Алексей]
Когда какую коллекцию использовать?
// ArrayList: нужен быстрый доступ по индексу, редкие вставки
ArrayList students = new ArrayList<>(); // список студентов
// LinkedList: частые вставки в начало/конец (очередь, стек)
LinkedList taskQueue = new LinkedList<>(); // очередь задач
// HashMap: поиск по ключу, справочники
HashMap prices = new HashMap<>(); // прайс-лист
// HashSet: уникальные значения, проверка наличия
HashSet visitedURLs = new HashSet<>(); // посещённые страницы
Итого: что мы узнали
- ✅ Коллекции — гибкие структуры данных с автоматическим изменением размера
- ✅ ArrayList: динамический массив; быстрый доступ по индексу O(1)
- ✅ LinkedList: двусвязный список; быстрые вставки в начало/конец O(1)
- ✅ HashMap: словарь ключ→значение; поиск за O(1)
- ✅ HashSet: только уникальные элементы; проверка за O(1)
- ✅
Collections— утилиты: sort, shuffle, min, max, frequency - ✅
Iterator— безопасное удаление при обходе коллекции - ✅ Generics
<String>: типизированные коллекции (ошибки на этапе компиляции) - ✅
removeIf()— элегантное условное удаление (Java 8+)