繁体   English   中英

使用Java 8 Streams,如何在HashMap中查找给定元素的最大值

[英]Using Java 8 Streams, how to find the max for a given element in a HashMap

我有一个产品的HashMap。 每个产品都有价格。 我知道如何找到具有最高价格的产品。 但是使用Java 8 Streams真的让我很困惑。 我试过这个但没有运气:

public Product getMostExpensiveProduct(HashMap<Integer, Product> items) {

    Product maxPriceProduct = items.entrySet()
            .stream()
            .reduce((Product a, Product b) ->
                    a.getPrice() < b.getPrice() ? b : a);

    return maxPriceProduct;
}

第一个问题是,由于您希望按价格找到最大Product ,因此最好使用items.values()作为流的源,然后您将拥有Stream<Product>而不是Stream<Map.Entry<Integer, Product>>

其次, reduce操作没有正确的类型。 因此,要使当前代码正常工作,您需要执行以下操作:

Optional<Map.Entry<Integer, Product>> result = 
      items.entrySet()
           .stream()
           .reduce((Map.Entry<Integer, Product> a, Map.Entry<Integer, Product> b) ->
                        a.getValue().getPrice() < b.getValue().getPrice() ? b : a);

return result.isPresent() ? result.get().getValue() : null;

第三, reduce操作的这个重载返回一个Optional<T>因此结果集的接收者类型必须是Optional<T>如上所示。

在上面,我们在Optional中没有值的情况下返回null

一个更好的解决方案是使方法返回一个类型Optional<Product> 这将向您或您的同事以及您的方法的所有未来用户提供文档,其中可能会给出结果为空的值。

这是一个更好的替代方法,可以在文档中返回null ,并确保此方法的用户安全地解包返回值。

无效在某些时候可能是危险的,并且在适当的情况下利用Optional可以带您走很长的路。

考虑到所有这些,您的代码将成为:

// example without returning an `Optional<T>`

public Product getMostExpensiveProduct(HashMap<Integer, Product> items) {
        Optional<Product> maxPriceProduct = 
           items.values()
                .stream()
                .reduce((Product a, Product b) ->
                        a.getPrice() < b.getPrice() ? b : a);

        return maxPriceProduct.orElse(null);
}

//示例返回Optional<T>

public Optional<Product> getMostExpensiveProduct(HashMap<Integer, Product> items) {
            Optional<Product> maxPriceProduct = 
               items.values()
                    .stream()
                    .reduce((Product a, Product b) ->
                            a.getPrice() < b.getPrice() ? b : a);

            return maxPriceProduct;
 }

无论如何, max方法更适合于此任务而不是reduce ,因此可以将其全部改进为:

Optional<Product> maxPriceProduct = 
           items.values()
                .stream()
                .max(Comparator.comparingInt(Product::getPrice));

只是注意到传递HashMap<Integer, Product>是没有意义的,因为你没有以任何方式使用Key ,所以这可能是为了将Collection<Product>作为参数编写的,所以它将成为:

public Product getMostExpensiveProduct(Collection<Product> products) {
    return Collections.max(products, Comparator.comparingInt(Product::getPrice));
}

但是,这将是一个单行的方法,所以你可以在需要的地方调用它:

Collections.max(items.values(), Comparator.comparingInt(Product::getPrice));

缺点是,如果传入的Collection为空,这将抛出NoSuchElementException

或者如果你关心null和空集合的所有检查(你应该):

public Optional<Product> getMostExpensiveProduct(Collection<Product> products) {
    if(products == null || products.isEmpty()){
        return Optional.empty();
    }
    return Optional.of(Collections.max(
            products, Comparator.comparingInt(Product::getPrice)));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM