我有一个产品的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;
}
答案 0 :(得分:9)
第一个问题是,由于您希望按价格找到最大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>
,如上所示。
在上面,我们在“可选”中没有值的情况下返回null
。
更好的解决方案是使方法返回类型Optional<Product>
。这将向您或您的同事以及您的方法的所有未来用户提供文档,其中可能会给出结果为空值。
这是返回null
文档的更好选择,并确保此方法的用户安全地解包返回值。
无效有时可能是危险的,并且在适当的情况下利用可选项可能会带您走很长的路。
考虑到所有这些,您的代码将成为:
// 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));
答案 1 :(得分:3)
注意到传递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));
缺点是,如果传入的NoSuchElementException
为空,则会抛出Collection
。
或如果你关心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)));
}