Java 8哈希映射

时间:2014-10-12 16:18:52

标签: java java-8 java-stream

我有一张地图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有效地(并且精美地)实现它?

2 个答案:

答案 0 :(得分:4)

你可以试试这个:

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<String,List<Double>>Pair<String,Double>关联,其中值是列表的最小值(或最大值),并且键保持不变,然后将每个Pair<String,Double>与{{1}}进行比较找到具有最低(或最高)值的那个。

答案 1 :(得分:4)

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

这仍然适用于从Pair<String,Double>中获取Map<String, List<Double>>,但可以做更多...