【问题标题】:Java 8 Hash MapJava 8 哈希映射
【发布时间】:2014-10-12 16:18:51
【问题描述】:

我有一张地图Map<String, List<Double>,我想在所有列表中找到最大值(或最小值)。 该函数应返回最大值(或最小值)和属于该值的键。

签名可能是

public static Pair<String,Double> getKeyValue(Map<String, List<Double>> map, BinaryOperator<Double> function)

获取地图和函数Double::maxDouble::min

如何使用 java 8、stream api 高效(且美观)地实现这一点?

【问题讨论】:

    标签: java java-8 java-stream


    【解决方案1】:

    BinaryOperator 不是该任务的良好规范,它可以直接用于归约以产生适当的值,例如最小值或最大值,但它不适合返回关联值,例如 Map 的键值。以这种方式使用它意味着实现必须执行额外的操作来找出BinaryOperator 实际做了什么,以便在减少期间选择正确的键值。更糟糕的是,它不能保证BinaryOperator 做了一些允许执行这种减少的事情,例如运算符可能返回一个既不是它的参数的值。

    对于这样的任务,Comparator 是更好的选择,因为它旨在指定排序并执行相关操作,例如查找最大值和最小值。实现可能如下所示:

    public static Pair<String,Double> getMinimumKeyValue(
        Map<String, List<Double>> map, Comparator<Double> function) {
    
        return map.entrySet().stream()
            .map(e->new Pair<>(e.getKey(), e.getValue().stream().min(function).get()))
            .min(Comparator.comparing(Pair::getRight, function)).get();
    }
    

    它被命名为getMinimumKeyValue,因为它会在你传入Comparator.naturalOrder()时返回最小的键/值对。

    但是你也可以通过Comparator.reverseOrder()获得最大值。

    而且它很容易修改以支持更广泛的用例:

    public static <K,V> Pair<K,V> getMinKeyValue(
        Map<K, ? extends Collection<V>> map, Comparator<? super V> function) {
    
        return map.entrySet().stream()
            .map(e->new Pair<>(e.getKey(), e.getValue().stream().min(function).get()))
            .min(Comparator.comparing(Pair::getRight, function)).get();
    }
    

    这仍然适用于从Map&lt;String, List&lt;Double&gt;&gt; 中获取Pair&lt;String,Double&gt;,但可以做更多事情......

    【讨论】:

      【解决方案2】:

      你可以试试这个:

      public static Pair<String,Double> getKeyValue(Map<String,List<Double>> map,
              BinaryOperator<Double> function) {
              return map.entrySet().stream()
                  .map(e -> new Pair<String,Double>(e.getKey(),e.getValue().stream().reduce(function).get()))
                  .reduce((p1,p2) -> function.apply(p1.getValue(),p2.getValue()).equals(p1.getValue()) ? p1 : p2)
                  .get();
      }
      

      说明:

      首先,将每个Entry&lt;String,List&lt;Double&gt;&gt; 关联到一个Pair&lt;String,Double&gt;,其中值是列表的最小值(或最大值)并且键保持不变,然后比较每个Pair&lt;String,Double&gt; 以找到具有最低(或最高)值。

      【讨论】:

      • 您在盒装的Doubles 上使用==,这似乎不太可能按预期工作。我倾向于尝试摆脱BinaryOperator&lt;Double&gt; 方法,而更喜欢Comparator....
      • 没错,但我只是将测试更改为a.equals(b) 来修复它。感谢您注意到这一点!
      • 我真的看不懂这个。也许是语法,缺失的对文字,无论如何,但我在阅读 Haskell 时遇到的问题较少。一般来说,函数式方法的可读性通常远低于 Java 中的普通旧风格。
      • 与其他完全设计为集成函数式编程的语言相比,Java 函数式风格有点冗长。你说得对,Java 中缺少元组语法可以使这段代码更清晰。
      • 啊!不要在这里使用 Optional.get,如果地图为空,它会抛出。使用 ifPresent、orElse 或 orElseThrow 等安全方法之一。
      猜你喜欢
      • 1970-01-01
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 2015-08-31
      相关资源
      最近更新 更多