I have this class:
class Product {
public double price;
public Product(double price) {
this.price = price;
}
}
And a Map:
Map<Product, Integer> products = new HashMap<>();
That contains several products added like so:
products.put(new Product(2.99), 2);
products.put(new Product(1.99), 4);
And I want to calculate the sum of all products multiple the values using streams? I tried:
double total = products.entrySet().stream().mapToDouble((k, v) -> k.getKey().price * v.getValue()).sum();
But it doesn't compile, I get “Cannot resolve method getValue()”.
I expect:
(2.99 * 2) (1.99 * 4) = 5.98 7.96 = 13.94
CodePudding user response:
The stream of entries needs single parameter lambda for each entry, not (k,v):
double total = products.entrySet().stream().mapToDouble(e -> e.getKey().price * e.getValue()).sum();
CodePudding user response:
You can also do it like so.
double sum = 0;
for(Entry<Product, Integer> e : products.entrySet()) {
sum = e.getKey().price * e.getValue();
}
System.out.println(sum);
prints
13.940000000000001
But you have a fundamental flaw in your class. You don't override equals or hashCode. So you're are you using the object reference as the key. Try doing the following:
System.out.println(products.get(new Product(1.99));
It will print null since there is no entry for that reference (it's a different object than the one used to store the value 4).
And finally you should make certain your keys are immutable. Otherwise, circumstances could result in the same error.
Check out why do I need to override hashcode and equals. And since it was mentioned in the comments, also check out what data type to use for money in java.
CodePudding user response:
Not directly related to your question, but I wouldn't use a map for what you are doing. Instead create a new class
public class ProductAmount {
private Product product;
private int amount;
public Product(Product product, int amount) {
this.product = product;
this.amount = amount;
}
public double getCombinedPrice() {
return product.price * amount;
}
}
Then you can use a List instead of a Map.
List<ProductAmount> products = Arrays.asList(
new ProductAmount(new Product(2.99), 2),
new ProductAmount (new Product(1.99), 4));
products.stream().mapToDouble(ProductAmount::getCombinedPrice).sum();
