1. Поиск элементов в коллекциях
Поиск с помощью стандартных методов
Когда у нас есть список, например, имён:
List<String> names = List.of("Анна", "Борис", "Виктория", "Анна", "Дмитрий");
Java предлагает несколько удобных методов для поиска:
- contains(Object o) — проверяет, есть ли элемент в коллекции.
- indexOf(Object o) — возвращает первый индекс вхождения элемента (или -1, если не найден).
- lastIndexOf(Object o) — возвращает последний индекс вхождения элемента (или -1).
Примеры:
System.out.println(names.contains("Анна")); // true
System.out.println(names.indexOf("Анна")); // 0
System.out.println(names.lastIndexOf("Анна")); // 3
System.out.println(names.contains("Сергей")); // false
Факт: Для коллекций типа Set методов indexOf и lastIndexOf нет — в Set вообще нет индексов, только уникальные значения.
Поиск по условию
Иногда нужно найти не конкретное значение, а элемент, который соответствует условию. Например, найти первое имя длиннее 6 символов. Обычный цикл for подходит отлично: как только нашли подходящий элемент — используйте break.
List<String> names = List.of("Анна", "Борис", "Виктория", "Анна", "Дмитрий");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // Нашли первый подходящий, можно выйти из цикла
}
}
System.out.println(found); // Виктория
Поиск максимального и минимального значения
Для коллекций со сравнимыми элементами (например, числа) можно быстро найти максимум и минимум с помощью класса Collections.
List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);
int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3
System.out.println("Максимум: " + max);
System.out.println("Минимум: " + min);
Важно: Элементы должны быть сравнимы (реализовывать Comparable), иначе потребуется передать компаратор.
2. Сортировка коллекций
Сортировка списка по умолчанию
Сортировать можно только изменяемые списки (например, ArrayList, LinkedList). Коллекции типа Set и Map не поддерживают сортировку напрямую.
По умолчанию сортировка идёт по «естественному порядку»: для чисел — возрастание, для строк — алфавит.
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
То же самое можно сделать через метод списка sort:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null означает: использовать естественный порядок
System.out.println(numbers); // [1, 3, 5, 7]
Сортировка с компаратором
Если нужно своё правило — например, сортировать строки по длине:
List<String> words = new ArrayList<>(List.of("кот", "слон", "муха", "носорог"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [кот, муха, слон, носорог]
В обратном порядке:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [носорог, муха, слон, кот]
Старый стиль через Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. Особенности сортировки разных коллекций
Сортировка изменяет только список
Методы сортировки (sort, Collections.sort) работают только с коллекциями, которые поддерживают порядок элементов (например, List). Для Set и Map такие методы не предусмотрены.
Попытка сортировать Set:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // Ошибка компиляции: sort ждёт List!
Если нужно получить отсортированный список из Set:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Сортировка Map: по ключам и по значениям
Сортировать Map напрямую нельзя, но можно:
- Получить список пар «ключ-значение»
- Отсортировать его нужным образом
- При необходимости собрать новый Map
Пример: сортировка по значениям
Map<String, Integer> scores = Map.of(
"Анна", 15,
"Борис", 20,
"Вика", 12
);
List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Вика: 12
// Анна: 15
// Борис: 20
Сортировка объектов по полю
Допустим, у нас есть класс пользователя:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
И список пользователей:
List<User> users = new ArrayList<>(List.of(
new User("Анна", 22),
new User("Борис", 18),
new User("Вика", 25)
));
Сортируем по возрасту:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Борис (18), Анна (22), Вика (25)]
В обратном порядке:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Вика (25), Анна (22), Борис (18)]
4. Типичные ошибки при поиске и сортировке коллекций
Ошибка №1: Сортировка неизменяемого списка. Списки, созданные через List.of(...), менять нельзя — при вызове sort получите UnsupportedOperationException.
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // Бросит исключение!
Ошибка №2: Сортировка Set или Map напрямую. Методы сортировки не работают с Set и Map. Если нужно отсортировать, сначала превратите данные в список.
Ошибка №3: Неправильное сравнение объектов. Не вычитайте целые числа «в лоб» при сравнении — возможны переполнения. Вместо u1.age - u2.age используйте Integer.compare или Comparator.comparingInt.
// users.sort((u1, u2) -> u1.age - u2.age); // Работает, но опасно при переполнении!
Ошибка №4: Использование contains для сложного поиска. Метод contains проверяет только полное совпадение (по equals). Если нужно искать по части строки или по полю объекта — используйте цикл с проверкой условия или компараторы/стримы.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ