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 .