-4

I need some help in finding the low expense and high expense in a month. I have a List Expenses where Expenses class is with the below values. Could you guide me on how to group them to get the expected output in Java-8? Thanks for the help in advance.

Expenses
type:Grocercies
kind:fruits
value:20
date:09/15/2020

Expenses
type:Grocercies
kind:vegetables
value:20
date:09/01/2020

Expenses
type:Grocercies
kind:fruits,pulses
value:10
date:09/25/2020

Expenses
type:Grocercies
kind:fruits,milk
value:18
date:09/23/2020

Expenses
type:Grocercies
kind:vegetables,pulses
value:15
date:09/10/2020

Combined Rates
Fruits,Pulses : 30
Vegetables,pulses : 35
Fruits,milk : 38

Expected output

Low expense : Fruits,Pulses 
High Expense : Fruits,milk

I tried grouping by the type(Groceries) i.e Map<String, List<Expenses>> and however I ended up again with a list, I am kind of lost on iterating the List. Your help is much appreciated.

flamingo
  • 21
  • 3
  • Couldn't you do it the same way you would have done it before Java 8, with a good old for loop? There is [Stream.min](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#min-java.util.Comparator-) and [max](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#max-java.util.Comparator-) if you want to use streams – user Sep 30 '20 at 17:06
  • 1
    Please provide the code snippet you have tried to implement. – Sujay Mohan Sep 30 '20 at 17:14
  • Does this help? https://stackoverflow.com/questions/41816264/concise-way-to-get-both-min-and-max-value-of-java-8-stream/43940961 – Abra Sep 30 '20 at 17:36

1 Answers1

0

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;
} 
flamingo
  • 21
  • 3