查找Java Map中的最大值

2023/06/07

1. 概述

在这个快速教程中,我们将探讨在Java Map中查找最大值的各种方法。我们还将看到Java 8中的新特性如何简化此操作。

在开始之前,让我们简要回顾一下在Java中如何比较对象

通常,对象可以通过从Comparable接口实现方法compareTo()来表达自然排序。但是,可以通过Comparator对象采用自然排序以外的排序。随着我们的继续,我们将看到更多细节。

2. Java 8之前

让我们先开始探讨如何在不使用Java 8功能的情况下找到最大值。

2.1 使用简单迭代

使用迭代,我们可以简单地遍历Map的所有条目以选择最大值,将当前最大值存储在变量中:

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 使用Collections.max()

现在让我们看看Collections类中的实用方法max()如何使我们免于自己编写大量这样的代码:

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(),它可以通过compareTo()来利用Entry值的自然排序,或者完全实现不同的排序。

3. Java 8之后

Java 8的特性可以简化我们上面以多种方式从Map获取最大值的操作。

3.1 将Collections.max()与Lambda表达式结合使用

让我们首先探讨Lambda表达式如何简化对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();
}

正如我们在这里看到的,Lambda表达式使我们免于定义成熟的功能接口,并提供了一种定义逻辑的简洁方法。要阅读有关Lambda表达式的更多信息,另请查看我们之前的文章

3.2 使用Stream

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转换。在这里,我们对MapEntry流使用了max(),这是归约操作的特例。有关Stream API的更多详细信息,请参见此处

我们还在这里使用了Optional API,它是Java 8中添加的一个容器对象,可能包含也可能不包含非空值。

3.3 将Stream与方法引用一起使用

最后,让我们看看方法引用如何进一步简化我们对Lambda表达式的使用:

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();
}

在Lambda表达式仅调用现有方法的情况下,方法引用允许我们直接使用方法名称来执行此操作。有关方法参考的更多详细信息,请查看之前的这篇文章

4. 总结

在本文中,我们看到了多种在Java Map中查找最大值的方法,其中一些使用了作为Java 8的一部分添加的功能。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章