I need to add up all amounts in MonthlyExpenses
list where types are equal.
In my code I am appending expenses
and obligations
to same list of MonthlyExpenses
.
Here is my code:
List<MonthlyExpenses> monthlyExpenses = new ArrayList<MonthlyExpenses>();
List<Expenses> expenses = getExpenses(borrower);
List<Obligations> obligations = getObligations(borrower);
if(expenses!=null){
monthlyExpenses.addAll(createMonthlyExpenses(expenses));
}
if(obligations!=null){
monthlyExpenses.addAll(createMonthlyObligations(obligations));
}
...
public class MonthlyExpenses {
private String type = null;
private BigDecimal amount = null;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}
The 1st IF statement
, if executed returns:
class MonthlyExpenses{
type: FOOD
amount: 150.00
}, class MonthlyExpenses{
type: UTILITIES
amount: 250.00
}, class MonthlyExpenses{
type: TRANSPORTATION
amount: 350.00
}, class MonthlyExpenses{
type: CHILD CARE
amount: 450.00
}, class MonthlyExpenses{
type: CREDIT CARDS
amount: 878.00
}, class MonthlyExpenses{
type: Other
amount: 2888.64
}
The 2nd IF statement
, if executed returns:
class MonthlyExpenses{
type: AUTO LOANS
amount: 200.00
}, class MonthlyExpenses{
type: CREDIT CARDS
amount: 300.00
}, class MonthlyExpenses{
type: INSTALLMENT LOANS
amount: 50.00
}, class MonthlyExpenses{
type: ALIMONY/SUPPORT
amount: 75.00
}, class MonthlyExpenses{
type: Other
amount: 10096.87
}
How do I check in List<MonthlyExpenses>
if types are equal and sum up those amounts and return that new list?
You can achieve this by using streams
and collectors
:
private static List<MonthlyExpense> createMonthlyExpenses(List<MonthlyExpense> expenses) {
Map<String, Double> sums = expenses.stream()
.collect(Collectors.groupingBy(
MonthlyExpense::getType,
Collectors.summingDouble(MonthlyExpense::getAmount))
);
return sums.entrySet().stream()
.map(entry -> new MonthlyExpense(entry.getKey(), entry.getValue()))
.sorted(Comparator.comparing(MonthlyExpense::getType))
.collect(Collectors.toList());
}
The way this work is by using collect
on all expenses grouping them by (groupBy
) their type
and using as a summing downstream collector. Then, you use this map (between types and total amounts) to create the objects with total expenses that you require. The following class is a full working application of this in action, for you to play with:
import java.util.*;
import java.util.stream.Collectors;
public class FinancialCalculator {
static class MonthlyExpense {
private String type;
private double amount;
public MonthlyExpense(String type, double amount) {
this.type = type;
this.amount = amount;
}
public String getType() { return type; }
public double getAmount() { return amount; }
public String toString() { return String.format("%s: %.2f", type, amount); }
}
private static List<MonthlyExpense> createMonthlyExpenses(List<MonthlyExpense> expenses) {
Map<String, Double> sums = expenses.stream()
.collect(Collectors.groupingBy(
MonthlyExpense::getType,
Collectors.summingDouble(MonthlyExpense::getAmount))
);
return sums.entrySet().stream()
.map(entry -> new MonthlyExpense(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
public static void main(String[] args) {
MonthlyExpense[] expenses = new MonthlyExpense[] {
new MonthlyExpense("UTILITIES", 75),
new MonthlyExpense("CREDIT", 1000),
new MonthlyExpense("UTILITIES", 50),
new MonthlyExpense("CREDIT", 2000),
new MonthlyExpense("UTILITIES", 150),
new MonthlyExpense("CAR", 344)
};
System.out.println(createMonthlyExpenses(Arrays.asList(expenses)));
}
}
Hope this helps.