I tried below approach. I am not sure is this an effective way. Is there any other way to implement it ?
public static void main(String[] args) {
List expenses = prepareBaseData();
Map<String, List> expensesOfAllKinds = expenses.stream()enter code here
.collect(Collectors.groupingBy(Expenses::getKind));
Listenter code here
finalOutPut = expensesOfAllKinds.entrySet().stream()
.map(expenseOfAKind -> calculateValue(expensesOfAllKinds, expenseOfAKind))
.flatMap(bean -> bean.stream()).collect(Collectors.toList());
System.out.println("finalOutPut");
ExpenseOutput minexpenseOutput = finalOutPut.stream()
.collect(Collectors.minBy(Comparator.comparing(ExpenseOutput::getValue))).get();
ExpenseOutput maxexpenseOutput = finalOutPut.stream()
.collect(Collectors.maxBy(Comparator.comparing(ExpenseOutput::getValue))).get();
System.out.println("minValue : " + minexpenseOutput.getKind() + " : " + minexpenseOutput.getValue());
System.out.println("maxValue : " + maxexpenseOutput.getKind() + " : " + maxexpenseOutput.getValue());
}
private static List<ExpenseOutput> calculateValue(Map<String, List<Expenses>> expensesOfAllKinds,
Entry<String, List<Expenses>> expenseOfAKind) {
List<Expenses> expenseOfAKindOfGrocery = expenseOfAKind.getValue();
List<Expenses> expensesOfOtherKinds = expensesOfAllKinds.entrySet().stream()
.filter(expenseOfDifferentKind -> !expenseOfDifferentKind.equals(expenseOfAKind))
.map(expenseOfDifferentKind -> expenseOfDifferentKind.getValue())
.flatMap(expenseOfDifferentKind -> expenseOfDifferentKind.stream()).collect(Collectors.toList());
return expenseOfAKindOfGrocery.stream()
.map(oneKindOfExpense -> mapAppropriateKindAndAddValue(oneKindOfExpense, expensesOfOtherKinds))
.flatMap(x -> x.stream()).collect(Collectors.toList());
}
private static List<ExpenseOutput> mapAppropriateKindAndAddValue(Expenses expenseOfAKind,
List<Expenses> expensesOfOtherKinds) {
return expensesOfOtherKinds.stream()
.filter(expenseOfOtherKind -> checkWhetherTheyHaveSameKind(expenseOfOtherKind, expenseOfAKind))
.map(expenseOfOtherKind -> addValueIfSameKindExists(expenseOfOtherKind, expenseOfAKind))
.collect(Collectors.toList());
}
private static boolean checkWhetherTheyHaveSameKind(Expenses expenseOfOtherKind, Expenses expenseOfAKind) {
List<String> expenseOfAKindList = Arrays.asList(expenseOfAKind.getKind().split(","));
List<String> expenseOfOtherKindList = Arrays.asList(expenseOfOtherKind.getKind().split(","));
return expenseOfOtherKindList.stream().allMatch(expense -> expenseOfAKindList.contains(expense));
}
private static ExpenseOutput addValueIfSameKindExists(Expenses expenseOfOtherKind, Expenses expenseOfAKind) {
ExpenseOutput output = new ExpenseOutput();
output.setValue(expenseOfOtherKind.getValue() + expenseOfAKind.getValue());
List<String> expenseOfAKindList = new ArrayList<>(Arrays.asList(expenseOfAKind.getKind().split(",")));
List<String> expenseOfOtherKindList = new ArrayList<>(Arrays.asList(expenseOfOtherKind.getKind().split(",")));
expenseOfOtherKindList.addAll(expenseOfAKindList);
Set<String> finalKind = expenseOfOtherKindList.stream().collect(Collectors.toSet());
output.setKind(String.join(",", finalKind));
return output;
}