Нахождение значения max / min в массиве примитивов с использованием Java

186

Это тривиально написать функцию для определения минимального / максимального значения в массиве, например:

/**
 * 
 * @param chars
 * @return the max value in the array of chars
 */
private static int maxValue(char[] chars) {
    int max = chars[0];
    for (int ktr = 0; ktr < chars.length; ktr++) {
        if (chars[ktr] > max) {
            max = chars[ktr];
        }
    }
    return max;
}

но разве это где-то уже не сделано?

Ник Хейнер
источник
8
Поможет массив примитива для массива контейнеров: stackoverflow.com/questions/3770289/…, а затем Collections.max(Arrays.asList()).
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
Я просто люблю, как глупа Java
Фарид

Ответы:

173

Использование Commons Lang (для конвертации) + Коллекции (в мин / макс)

import java.util.Arrays;
import java.util.Collections;

import org.apache.commons.lang.ArrayUtils;

public class MinMaxValue {

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};

        List b = Arrays.asList(ArrayUtils.toObject(a));

        System.out.println(Collections.min(b));
        System.out.println(Collections.max(b));
   }
}

Обратите внимание, что Arrays.asList()оборачивает базовый массив, поэтому он не должен занимать слишком много памяти и не должен выполнять копирование элементов массива.

Майкл Рутерфурд
источник
9
что такоеArrayUtils
Башир аль-Момани
4
Arrays.asList()должно быть хорошо, но ArrayUtils.toObject()будет копировать каждый элемент aв новый массив Character.
EM
5
Arrays.asList(a)не работает Вы не можете составить список примитивов ( List<char>в этом случае). Сначала вам нужно преобразовать примитивные значения в объекты, и именно поэтому они ArrayUtils.toObjectиспользуются.
nessa.gp
96

Вы можете просто использовать новые Java 8 Streamсек , но вы должны работать с int.

streamМетод класса полезности Arraysдает Вам , IntStreamна котором вы можете использовать minметод. Вы можете также сделать max, sum, average, ...

getAsIntМетод используется для получения значения изOptionalInt

import java.util.Arrays;

public class Test {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        int min = Arrays.stream(tab).min().getAsInt();
        int max = Arrays.stream(tab).max().getAsInt();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max)
    }

}

== UPDATE ==

Если время выполнения важно, и вы хотите просмотреть данные только один раз, вы можете использовать summaryStatistics()метод, подобный этому

import java.util.Arrays;
import java.util.IntSummaryStatistics;

public class SOTest {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
        int min = stat.getMin();
        int max = stat.getMax();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max);
    }
}

Этот подход может дать лучшую производительность, чем классический цикл, потому что summaryStatisticsметод является операцией сокращения и допускает распараллеливание.

Ортомала Локни
источник
57

библиотеке Google Guava есть методы min и max в классах Chars, Ints, Longs и т. Д.

Так что вы можете просто использовать:

Chars.min(myarray)

Никаких преобразований не требуется, и, по-видимому, они эффективно реализованы.

Эндрю Маккинли
источник
4
Он реализован примерно так же, как в вопросе, за исключением того, что он генерирует исключение IllegalArgumentException для массива длиной 0. ( code.google.com/p/guava-libraries/source/browse/trunk/src/com/… )
ColinD
3
Это лучшее решение всего здесь. Избегает всего этого путаницы в java.util.Arrays # asList.
Конг
20

Да, это сделано в классе Коллекции . Обратите внимание, что вам нужно будет преобразовать массив примитивных символов в Character [] вручную.

Короткая демонстрация:

import java.util.*;

public class Main {

    public static Character[] convert(char[] chars) {
        Character[] copy = new Character[chars.length];
        for(int i = 0; i < copy.length; i++) {
            copy[i] = Character.valueOf(chars[i]);
        }
        return copy;
    }

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};
        Character[] b = convert(a);
        System.out.println(Collections.max(Arrays.asList(b)));
    }
}
Барт Киерс
источник
1
Collections.min (MyCollection); Если вы хотите использовать его для массивов, вы можете сделать это как Collections.min (Arrays.asList (myArray));
Зед
3
преобразование a char []в a Character []только для определения максимума довольно неэффективно - лучше создать вспомогательный класс со статическими методами для каждого типа примитива, подобный следующему java.util.Arrays: java.sun.com/javase/6/docs/api/java/util/Arrays.html
Кристоф
@Christoph: да, если размер массива большой, я бы согласился. Просто указывать, что это «неэффективно», не имеет смысла, если рассматриваемое приложение выполняет много вызовов базы данных и / или операций ввода-вывода, а размер массива (относительно) мал.
Барт Киерс
Вы должны использовать Character.valueOf(chars[i])вместо new Character(chars[i])соображений производительности: java.sun.com/javase/6/docs/api/java/lang/…
Кристоф
@Christoph Кристоф прав, неэффективно и глупо преобразовать массив в коллекцию для минимального поиска.
AlexWien
16
import java.util.Arrays;

public class apples {

  public static void main(String[] args) {
    int a[] = {2,5,3,7,8};
    Arrays.sort(a);

     int min =a[0];
    System.out.println(min);
    int max= a[a.length-1];
    System.out.println(max);

  }

}
Lubna_Nsour
источник
4
Пожалуйста, предоставьте некоторые объяснения.
Майк Стокдейл
3
Я думаю, что это значит сказать, что если вы сортируете массив (в порядке возрастания), то по определению минимальное значение всегда будет в первой позиции, a [0], а максимальное значение всегда будет в последней позиции , [длина волны-1].
Джефф
1
Это законный и полезный способ решения проблемы. В чем недостаток его использования по сравнению с другими?
Alex
8
сложность времени @alex - сортировка в лучшем случае является делом O (nlogn), в то время как подход Майкла Резерфурда - O (n).
jajdoo
3
Нам не нужно сортировать, так как одной итерации по списку достаточно, чтобы найти минимальное и максимальное значения.
akhil_mittal
11

У меня есть небольшой вспомогательный класс во всех моих приложениях с такими методами:

public static double arrayMax(double[] arr) {
    double max = Double.NEGATIVE_INFINITY;

    for(double cur: arr)
        max = Math.max(max, cur);

    return max;
}
Sauer
источник
1
Вы должны использовать double max = Double.NEGATIVE_INFINITY; вместо double max = Double.MIN_VALUE; Поскольку MIN_VALUE для двойника положительный
крем
1
... или вы можете установить max для первого элемента в массиве и перейти от второго элемента, смотрите мой ответ.
Николас Гамильтон
3

Вы можете легко сделать это с IntStreamиmax() методу.

пример

public static int maxValue(final int[] intArray) {
  return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}

объяснение

  1. range(0, intArray.length)- Чтобы получить поток с таким количеством элементов, сколько присутствует в intArray.

  2. map(i -> intArray[i])- Сопоставить каждый элемент потока с фактическим элементом intArray.

  3. max()- Получить максимальный элемент этого потока как OptionalInt.

  4. getAsInt()- Разверни OptionalInt. (Вы также можете использовать здесь:, orElse(0)на случай, если OptionalIntпусто.)

winklerrr
источник
2

Вот вспомогательный класс, предоставляющий min/maxметоды для примитивных типов: Primitives.java

Christoph
источник
2
import java.util.Random;

public class Main {

public static void main(String[] args) {
   int a[] = new int [100];
   Random rnd = new Random ();

    for (int i = 0; i< a.length; i++) {
        a[i] = rnd.nextInt(99-0)+0;
        System.out.println(a[i]);
    }

    int max = 0;          

    for (int i = 0; i < a.length; i++) {
        a[i] = max;


        for (int j = i+1; j<a.length; j++) {
            if (a[j] > max) {
               max = a[j];
            }

        }
    }

    System.out.println("Max element: " + max);
}
}
Mark2
источник
2
    public int getMin(int[] values){
        int ret = values[0];
        for(int i = 1; i < values.length; i++)
            ret = Math.min(ret,values[i]);
        return ret;
    }
Николас Гамильтон
источник
Это для чисел, intно вопрос задает для примитивных значенийint, long, char, byte....
IgniteCoders
2

Решение с reduce():

int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);

// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97

В приведенном выше коде, reduce()возвращает данные в Optionalформате, который можно преобразовать в intпоgetAsInt() .

Если мы хотим сравнить максимальное значение с определенным числом, мы можем установить начальное значение в reduce():

int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100

В приведенном выше коде, когда reduce()в качестве первого параметра указан идентификатор (начальное значение), он возвращает данные в том же формате, что и идентификатор. С помощью этого свойства мы можем применить это решение к другим массивам:

double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Саймон З.
источник
1

Пример с плавающей точкой:

public static float getMaxFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[data.length - 1];
}

public static float getMinFloat(float[] data) {

    float[] copy = Arrays.copyOf(data, data.length);
    Arrays.sort(copy);
    return copy[0];
}
Андрей
источник
Хотя ваше решение будет работать, но оно увеличит сложность времени до O (nlogn), в то время как min можно легко найти в O (n), используя другие ответы.
Прамод
просто сумасшедший, чтобы использовать сортировку в этой ситуации.
Николас Гамильтон
Это может быть полезно, когда требуется первое n> 1 наименьшее / наибольшее значение с некоторым ремонтом.
biziclop
1

Вот решение, чтобы получить максимальное значение примерно за 99% прогонов (измените 0,01, чтобы получить лучший результат):

public static double getMax(double[] vals){
    final double[] max = {Double.NEGATIVE_INFINITY};

    IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
            .forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);

    return max[0];
}

(Не совсем серьезно)

mnzl
источник
;-) Это не совсем серьезно, хорошо. Стесняюсь высказаться…
Оле В.В.
0

Передайте массив методу, который сортирует его, Arrays.sort()чтобы он только сортировал массив, который использует метод, затем устанавливает min в array[0]и max в array[array.length-1].

whoduexpect
источник
3
Вероятно, стоит отметить, что а) это модифицирует массив, и б) для больших массивов это более дорогое решение, чем O (nlog n), а не O (n)
Давидшельдон
0

Основной способ получить минимальное / максимальное значение массива. Если вам нужен несортированный массив, вы можете создать копию или передать ее методу, который возвращает мин или макс. Если нет, отсортированный массив лучше, так как в некоторых случаях он работает быстрее.

public class MinMaxValueOfArray {
    public static void main(String[] args) {
        int[] A = {2, 4, 3, 5, 5};
        Arrays.sort(A);
        int min = A[0];
        int max = A[A.length -1];
        System.out.println("Min Value = " + min);        
        System.out.println("Max Value = " + max);
    }
}
Ким Г.
источник
2
Проблема с сортировкой состоит в том, что у нее есть O (n log n) для проблемы O (n). Но это лучше, чем остальные три ответа «отсортировать массив», которые уже даны.
Teepeemm