Научитесь находить наименьший и наибольший элемент в массиве в Java. Мы обсудим различные подходы от простых итераций до API потоков.
В приведенных примерах мы берем массив значений int. Мы можем применить все приведенные решения к массиву объектов или пользовательских классов. В случае пользовательских объектов нам нужно только переопределить метод equals() и предоставить правильную логику для сравнения двух экземпляров.
int[] items = { 10, 0, 30, 2, 7, 5, 90, 76, 100, 45, 55 }; // Min = 0, Max = 100
1. Найдите Макс/Мин с помощью Stream API
Потоки Java предоставляют множество полезных классов и методов для выполнения агрегатных операций. Давайте обсудим некоторые из них.
1.1.Stream.max() и Stream.min()
Интерфейс Stream предоставляет два метода max() и min(), которые возвращают наибольший и наименьший элемент из базового потока.
Оба метода могут использовать пользовательский экземпляр Comparator, если нам нужна индивидуальная логика сравнения между элементами.
Для примитивов у нас есть IntStream, LongStream и DoubleStream для поддержки последовательных и параллельных агрегатных операций над элементами потока. Мы можем использовать метод java.util.Arrays.stream() для преобразования массива в Stream, а затем выполнить над ним любую операцию.
int max = Arrays.stream(items).max().getAsInt(); // 100int min = Arrays.stream(items).min().getAsInt(); // 0
1.2.IntStream.summaryStatistics()
В приведенном выше примере мы находим максимальные и минимальные элементы массива в два отдельных шага. Мы создаем поток два раза и работаем с ним два раза. Это полезно, когда нам нужно найти только максимальный или минимальный элемент.
Если нам нужно найти и максимальный, и минимальный элемент, то получение максимального и минимального элемента из массива за одну итерацию имеет полный смысл. Мы можем сделать это с помощью экземпляра IntSummaryStatistics. Похожий экземпляр доступен также для LongStream и DoubleStream.
IntSummaryStatistics stats = Arrays.stream(items).summaryStatistics();stats.getMax(); //100stats.getMin(); //0
2. Коллекции.min() и Коллекции.max()
Класс Collections предоставляет агрегатные операции для элементов в коллекции, такой как List. Мы можем преобразовать массив в List и использовать эти API для поиска максимальных и минимальных элементов.
В данном примере мы преобразуем int[] в Integer[]. Если у вас уже есть Object[], то вы можете напрямую передать массив в API Arrays.asList().
Integer min = Collections.min(Arrays.asList(ArrayUtils.toObject(items)));Integer max = Collections.max(Arrays.asList(ArrayUtils.toObject(items)));
3. Сортировка массива
Сортировка массива также является хорошим подходом для небольших массивов. Для больших массивов сортировка может оказаться проблемой производительности, поэтому выбирайте с умом.
В отсортированном массиве минимальные и максимальные элементы будут находиться в начале и конце массива.
Arrays.sort(items);max = items[items.length - 1]; //100min = items[0]; //0
4. Итерация массива
Это самая базовая версия решения. Псевдокод:
Инициализируем максимум и минимум первым элементом массиваИтерация массива со второй позиции(индекс 1)Сравните i-й элемент с макс. и мин.если текущий элемент больше максимальногоустановить макс = текущий элементelseif текущий элемент меньше минимумаустановить min = текущий элемент
После завершения цикла переменные max и min будут ссылаться на наибольший и наименьший элементы в массиве.
max = items[0];min = items[0];for(int i = 1; i < items.length; i++) {if(items[i] > max) {max = items[i];}else if(items[i] < min) {min = items[i];}}System.out.println(max); //100System.out.println(min); //0
5. Рекурсия
Рекурсия обеспечивает лучшую производительность для несортированного массива большого размера. Обратите внимание, что мы пишем рекурсивный вызов для максимальных и минимальных элементов отдельно. Если нам нужно найти оба элемента за один вызов, нам нужно будет изменить программу в соответствии с требованиями.
Это решение по сути представляет собой алгоритм «Разделяй и властвуй», в котором мы обрабатываем только текущий индекс и результат остальных(рекурсивный вызов) и объединяем их для получения конечного результата.
Для получения максимального количества элементов, для каждого элемента мы возвращаем больший из текущих элементов в сравнении и все элементы с большим индексом. Аналогичный подход используется для поиска минимального элемента.
min = getMax(items, 0, items[0]); //0min = getMin(items, 0, items[0]); //100public static int getMax(final int[] numbers, final int a, final int n) {return a >= numbers.length ? n: Math.max(n, getMax(numbers, a + 1, numbers[a] > n ? numbers[a] : n));}private static int getMin(final int[] numbers, final int a, final int n) {return a == numbers.length ? n: Math.min(n, getMin(numbers, a + 1, numbers[a] < n ? numbers[a] : n));}
6. Заключение
В этом коротком уроке Java мы изучили различные способы поиска максимального и минимального элемента массива в Java. Мы научились использовать Stream API, Collections API, простые итерации и продвинутые методы, такие как рекурсия.
Для меньших массивов мы должны предпочесть читаемость кода и использовать API потоков или коллекций. Для больших массивов, где мы получим заметные улучшения производительности, можно рассмотреть использование рекурсии.