Math.max: примеры (JAVA)

Примеры и разбор Math.max в Java
Раздел: Математические операции
Math.max(int a, int b): int

Описание Math.max()

В Java Math.max - это набор статических перегруженных методов в классе java.lang.Math, предназначенных для выбора большего из двух примитивных числовых значений. Методы доступны для типов int, long, float и double. Сигнатуры выглядят примерно так: int max(int a,int b), long max(long a,long b), float max(float a,float b), double max(double a,double b).

Возвращаемое значение имеет тот же примитивный тип, что и параметры. Поведение при особых значениях для плавающей точки:

  • Если один из аргументов типа float или double равен NaN, результат будет NaN.
  • При сравнении +0.0 и -0.0 результатом будет +0.0, так как +0 считается больше по правилу сравнения IEEE 754, применяемому в Java.

При передаче смешанных литералов или выражений с разными типами применяются правила приведения типов и перегрузки: если один аргумент является long, другой int, будет выбрана версия с long, при этом int неявно приводится. При передаче обёрток (Integer, Long и т. п.) происходит автеразупаковка в примитивы; при значении null возможен NullPointerException.

Класс Math содержит также аналогичные методы в StrictMath, а примитивные классы-обёртки предлагают свои «max»-методы (см. раздел альтернатив).

Короткие примеры использования

Несколько простых примеров для разных перегрузок и ситуаций.

Пример для int:

int a = 5;
int b = 9;
System.out.println(Math.max(a, b));
9

Пример для long с автоматическим повышением типа:

System.out.println(Math.max(1, 2L)); // int и long
2

Поведение с double и NaN:

double x = Double.NaN;
double y = 1.0;
System.out.println(Math.max(x, y));
NaN

Сравнение знаковых нулей:

double p = +0.0;
double n = -0.0;
System.out.println(Math.max(p, n));
System.out.println(1 / Math.max(p, n)); // показать знак нуля
0.0
Infinity

Ошибка при автеразупаковке (null в обёртке):

Integer ai = null;
System.out.println(Math.max(ai, 1));
java.lang.NullPointerException

Аналоги внутри Java и когда их выбирать

Несколько вариантов выбора максимального значения в Java, отличных от Math.max:

  • Integer.max, Long.max, Double.max и Float.max - статические методы обёрток, выполняющие ту же задачу для соответствующих примитивов. Подходящи при явно используемых типах и для читабельности.
  • Collections.max - выбирает максимум в коллекции объектов, требует, чтобы элементы реализовали Comparable или передать Comparator. Полезно для списков и наборов объектов.
  • Stream.max и примитивные стримы (IntStream.max(), DoubleStream.max()) - удобны при поиске максимума в потоках данных, возвращают Optional-значения.
  • BigInteger.max и BigDecimal.max - методы экземпляров для больших целых и десятичных чисел; следует применять при необходимости точной арифметики без плавающей точки.
  • StrictMath.max - функционально эквивалентен Math.max, применяется там, где требуется поведение, полностью совместимое с эталонной реализацией.

Аналоги в других языках и отличия

Краткие примеры подходящих аналогов в популярных языках и важные отличия.

JavaScript (переменное число аргументов):

// JS
console.log(Math.max(1, 5, 3));
console.log(Math.max());
console.log(Math.max(1, NaN));
5
-Infinity
NaN

Python (функция max для итерируемых и нескольких аргументов):

# Python
print(max(1, 5, 3))
print(max([2, 7, 4]))
5
7

PHP (функция max):

// PHP
echo max(1, 4, 2);
4

C# (Math.Max):

// C#
System.Console.WriteLine(System.Math.Max(1, 3));
System.Console.WriteLine(System.Math.Max(double.NaN, 1.0));
3
NaN

Go (пакет math для float64):

// Go
import "math"
fmt.Println(math.Max(1.0, 2.5))
2.5

Kotlin (функция maxOf и kotlin.math.max):

// Kotlin
println(maxOf(1, 3))
println(kotlin.math.max(1.0, 2.0))
3
2.0

Lua (math.max):

-- Lua
print(math.max(1, 8, 5))
8

SQL (GREATEST, поведение с NULL зависит от СУБД):

-- PostgreSQL/MySQL
SELECT GREATEST(1, 4, 2);
SELECT GREATEST(NULL, 1, 2);
3
NULL

Отличия от Java:

  • Во многих языках функция принимает переменное число аргументов (JS, Python, PHP, Lua), тогда как Java Math.max - только бинарная.
  • Поведение с NaN и NULL/None/NaN различается: в JS Math.max() при отсутствии аргументов возвращает -Infinity, а в Python вызов без аргументов вызывает ошибку.
  • В Go стандартная функция работает только с float64; для целых типов нужен каст или своя реализация.
  • SQL-функции работают с NULL по правилам конкретной СУБД, часто возвращают NULL при наличии NULL-аргумента.

Типичные ошибки и подводные камни

Некоторые распространённые ошибки при работе с Math.max и примеры:

NullPointerException при автеразупаковке:

Integer x = null;
int y = 5;
System.out.println(Math.max(x, y));
java.lang.NullPointerException

Ожидание работы с массивом напрямую (нет вариативной версии):

int[] arr = {1, 4, 2};
// неверно: Math.max(arr); // компиляция не пройдёт
Ошибка компиляции: нет подходящей перегрузки

Неочевидное поведение при сравнениях с NaN и знаковыми нулями:

System.out.println(Math.max(Double.NaN, 1.0));
System.out.println(Math.max(+0.0, -0.0));
NaN
0.0

Погрешности при работе с float/double, приводящие к кажущемуся «неправильному» максимуму (обычно связано с представлением чисел с плавающей точкой):

float a = 0.1f + 0.2f;
float b = 0.3f;
System.out.println(a == b);
System.out.println(Math.max(a, b));
false
0.30000004

Изменения в последних версиях Java

Сам Math.max как набор перегрузок для примитивов не претерпевал существенных изменений в недавних релизах. Более заметные изменения связаны с дополнениями в стандартной библиотеке:

  • В Java 8 появились статические методы max в обёртках, таких как Integer.max и Long.max, что повышает удобство при работе с примитивами и повышает выразительность кода.
  • Поведение Math.max осталось совместимым с предыдущими версиями Java, включая обработку NaN и знаковых нулей.

Расширенные примеры и редкие сценарии

Несколько более сложных и практических примеров применения при обработке данных и в алгоритмах.

Нахождение максимума в массиве с использованием цикла и Math.max:

Пример java
int[] arr = {3, 7, 2, 9, 5};
int max = Integer.MIN_VALUE;
for (int v : arr) {
    max = Math.max(max, v);
}
System.out.println(max);
9

Использование IntStream и ссылки на метод:

Пример java
int[] nums = {4, 1, 8, 3};
int max = java.util.Arrays.stream(nums).reduce(Math::max).orElse(Integer.MIN_VALUE);
System.out.println(max);
8

Клиппинг (ограничение значения диапазоном) с помощью вложенных вызовов:

Пример java
int clamp = Math.max(0, Math.min(value, 100));
// value будет приведено к диапазону [0,100]
(в зависимости от value)

Максимум для больших чисел с использованием BigInteger:

Пример java
java.math.BigInteger a = new java.math.BigInteger("12345678901234567890");
java.math.BigInteger b = new java.math.BigInteger("9876543210987654321");
System.out.println(a.max(b));
12345678901234567890

Использование в динамическом программировании и рекуррентных формулах (пример для одной итерации):

Пример java
// при вычислении максимальной стоимости пути
int keep = 10; // текущий выбор
int take = 15; // другой вариант
int best = Math.max(keep, take);
System.out.println(best);
15

Поиск максимума в коллекции объектов через Comparator (альтернатива для объектов):

Пример java
class Person { int age; Person(int a){age=a;} int getAge(){return age;} }
java.util.List list = java.util.List.of(new Person(20), new Person(35), new Person(28));
Person oldest = java.util.Collections.max(list, java.util.Comparator.comparingInt(Person::getAge));
System.out.println(oldest.getAge());
35

Обработка NaN перед сравнением (если требуется игнорировать NaN и выбирать реальное число):

Пример java
double a = Double.NaN;
double b = 2.0;
double safeMax = Double.isNaN(a) ? b : (Double.isNaN(b) ? a : Math.max(a, b));
System.out.println(safeMax);
2.0

джава Math.max function comments

En
Math.max Возвращает большее из двух значений