javalambdajava-8java-stream

Get item from first list of list inside list - java 8


I have two lists and I need check the max rate and when find it, retrieve bankConversionFees item

for (BankConversionFees bankConversionFees : allFees) {
    for (FeesHistory hist : bankConversionFee.getFeesHistory()) {
        //check FeesHistory with max value of hist.getRate()
    }
}

The classes:

public class BankConversionFees{
 private String name;
 private List<FeesHistory> feesHistory;
}

public class FeesHistory {
private Double rate;
}

I achieved the result with the code below but I'm not sure if it's the best way

Comparator<FeesHistory> comparator = Comparator.comparingDouble(FeesHistory::getRate);
FeesHistory maxFees = allFees.stream() //
                .filter(bank -> !bank.getFeesHistory().isEmpty()) //
                .map(bank -> bank.getFeesHistory().stream().max(comparator).get()) //
                .max(comparator).get();
    
Optional<BankConversionFee> maxBank = allFees.stream() //
                .filter(bank -> !bank.getFeesHistory().isEmpty()) //
                .filter(bank -> bank.getFeesHistory().contains(maxFees)) //
                .map(b -> b) //
                .findFirst();

Solution

  • Conceptually this can be reframed as trying to get the "greatest" BankConversionFees, where "greatest" means the one containing the single greatest individual rate.

    This can be represented in a simple, straightforward manner using Stream.max(Comparator) with a comparator that compares the BankConversionFees based on the largest rate (treating any empty fee history lists as smaller than any non-emtpy ones):

    Comparator<BankConversionFees> comparator = Comparator.comparing(
            f -> f.getFeesHistory().stream().map(FeesHistory::getRate).max(Comparator.naturalOrder()),
            Comparator.nullsFirst(Comparator.comparing(o -> o.orElse(null))));
    
    return allFees.stream().max(comparator);
    

    If you want to continue to return an empty optional in the case where no BankConversionFees has any rates, as opposed to returning one of the fees without rates, you can filter accordingly:

    Comparator<BankConversionFees> comparator = Comparator.comparing(
            h -> h.getFeesHistory().stream().map(FeesHistory::getRate).max(Comparator.naturalOrder()).orElseThrow());
    
    return allFees.stream().filter(f-> !f.getFeesHistory().isEmpty()).max(comparator);