-2

I have one List, want to write a stream based code to find the average price.

  1. Input parameter is a list of PT class with Qty and Price fields.

Input:

[PT(qty=300, price=57.8),           
PT(qty=200, price=57.5),        
PT(qty=240, price=57.2)]       

Output:

Price = (300 x 57.86 +200 x 57.5 + 240 x 57.28) / 740 = 57.57

PT class:

class PT{       
   BigDecimal price;      
   BigDecimal qty;  
}

I am bit confused how to write one function that produce the above mentioned output. It will be a great help if somebody can throw some light. Thanks

azro
  • 53,056
  • 7
  • 34
  • 70
  • 1
    You can't do it manually in a one-way Stream, as you can't manage the sum of produts AND the total sum in one way, use the given duplicate link, or usr a for-each loop – azro Oct 29 '19 at 09:25
  • there's an answer with extensive explanation here: [https://stackoverflow.com/questions/22635945/adding-up-bigdecimals-using-streams](https://stackoverflow.com/questions/22635945/adding-up-bigdecimals-using-streams) – Itamar Lev Oct 29 '19 at 09:38
  • @Naman I don't think you dupe target will be sufficient for OP, as they needs to use weighted average. It is probably easier to convert [Calculate weighted average with Java 8 streams](https://stackoverflow.com/a/40420823/525036) to use `BigDecimal` instead of `double`/`long`. – Didier L Oct 29 '19 at 11:07
  • 1
    @azro You _can_ actually do it in a one-way stream, by using a custom collector. – Didier L Oct 29 '19 at 11:08

1 Answers1

0

As you have 2 parameters in you class, you can't use the classic BigDecimal summary statistics

You may use a loop:

List<PT> list = new ArrayList<>() {{
    add(new PT(57.8, 300));
    add(new PT(57.5, 200));
    add(new PT(57.2, 240));
}};

BigDecimal sum = BigDecimal.ZERO, product = BigDecimal.ZERO;
for (PT p : list) {
    sum = sum.add(p.getQty());
    product = product.add(p.getQty().multiply(p.getPrice()));
}
double result = product.divide(sum, RoundingMode.CEILING).doubleValue();
System.out.println(result);

If your values are not so big, and can fit in a double max 1.7976931348623157e+308 , use it it'll cost you less

azro
  • 53,056
  • 7
  • 34
  • 70