Перейти к основному содержимому

Поиск наибольшего значения в карте Java

· 4 мин. чтения

1. Обзор

В этом кратком руководстве мы рассмотрим различные способы поиска максимального значения в карте Java . Мы также увидим, как новые возможности Java 8 упростили эту операцию.

Прежде чем мы начнем, давайте кратко вспомним, как объекты сравниваются в Java.

Обычно объекты могут выражать естественный порядок путем реализации метода compareTo() из интерфейса Comparable . Однако порядок, отличный от естественного, может использоваться через объект Comparator . Мы увидим их более подробно по ходу дела.

2. До Java 8

Давайте начнем сначала с изучения того, как мы можем найти наибольшее значение без функций Java 8.

2.1. Использование простой итерации

Используя итерацию, мы могли бы просто пройтись по всем записям карты , чтобы выбрать самое высокое значение, сохраняя текущее самое высокое значение в переменной:

public <K, V extends Comparable<V>> V maxUsingIteration(Map<K, V> map) {
Map.Entry<K, V> maxEntry = null;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (maxEntry == null || entry.getValue()
.compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry.getValue();
}

Здесь мы также используем дженерики Java для создания метода, который можно применять к различным типам.

2.2. Использование Коллекции.max()

Теперь давайте посмотрим, как служебный метод max() в классе Collections может избавить нас от необходимости писать многое из этого самостоятельно:

public <K, V extends Comparable<V>> V maxUsingCollectionsMax(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), new Comparator<Entry<K, V>>() {
public int compare(Entry<K, V> e1, Entry<K, V> e2) {
return e1.getValue()
.compareTo(e2.getValue());
}
});
return maxEntry.getValue();
}

В этом примере мы передаем объект Comparator в max() , который может использовать естественный порядок значений Entry через compareTo() или вообще реализовать другой порядок.

3. После Java 8

Возможности Java 8 могут упростить нашу попытку получить максимальное значение из карты более чем одним способом.

3.1. Использование Collections.max() с лямбда-выражением

Давайте начнем с изучения того, как лямбда-выражения могут упростить вызов Collections.max() :

public <K, V extends Comparable<V>> V maxUsingCollectionsMaxAndLambda(Map<K, V> map) {
Entry<K, V> maxEntry = Collections.max(map.entrySet(), (Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue()));
return maxEntry.getValue();
}

Как мы видим здесь, лямбда-выражения избавляют нас от определения полноценного функционального интерфейса и обеспечивают краткий способ определения логики. Чтобы узнать больше о лямбда-выражениях, также ознакомьтесь с нашей предыдущей статьей .

3.2. Использование потока

Stream API — еще одно дополнение к Java 8 , которое значительно упростило работу с коллекциями:

public <K, V extends Comparable<V>> V maxUsingStreamAndLambda(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max((Entry<K, V> e1, Entry<K, V> e2) -> e1.getValue()
.compareTo(e2.getValue())
);

return maxEntry.get().getValue();
}

Этот API предлагает множество запросов обработки данных, таких как преобразование map-reduce для коллекций. Здесь мы использовали max() для потока Map Entry , что является частным случаем операции сокращения. Более подробная информация о Stream API доступна здесь .

Мы также используем здесь дополнительный API, который представляет собой объект-контейнер, добавленный в Java 8, который может содержать или не содержать ненулевое значение. Более подробную информацию о факультативе можно получить здесь .

3.3. Использование Stream со ссылкой на метод

Наконец, давайте посмотрим, как ссылки на методы могут еще больше упростить использование лямбда-выражений:

public <K, V extends Comparable<V>> V maxUsingStreamAndMethodReference(Map<K, V> map) {
Optional<Entry<K, V>> maxEntry = map.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getValue));
return maxEntry.get()
.getValue();
}

В тех случаях, когда лямбда-выражения просто вызывают существующий метод, ссылка на метод позволяет нам сделать это, используя имя метода напрямую. Для получения более подробной информации о ссылках на методы см. предыдущую статью .

4. Вывод

В этой статье мы рассмотрели несколько способов нахождения наибольшего значения в карте Java , некоторые из которых использовали функции, добавленные как часть Java 8.

Как всегда, код примеров доступен на GitHub .