Passing a method reference as parameter

2k Views Asked by At

In a case like this:

public class Order {
    List<Double> prices = List.of(1.00, 10.00, 100.00);
    List<Double> pricesWithTax = List.of(1.22, 12.20, 120.00);

    Double sumBy(/* method reference */) {
        Double sum = 0.0;
        for (Double price : /* method reference */) {
            sum += price;
        }
        return sum;
    }

    public List<Double> getPrices() { return prices; }
    public List<Double> getPricesWithTax() { return pricesWithTax; }
}

how can I declare the sumBy method in a way that can be called like this:

Order order = new Order();
var sum = order.sumBy(order::getPrices);
var sumWithTaxes = order.sumBy(order::getPricesWithTax);

I'm not using the Java 8 API for the sum because my goal is only to understand how pass a method reference.

4

There are 4 best solutions below

4
On BEST ANSWER

You seem to want a Supplier like

Double sumBy(Supplier<List<Double>> f) {
    Double sum = 0.0;
    for (Double price : f.get()) {
        sum += price;
    }
    return sum;
}

Your List.of syntax was giving me errors. So I did

List<Double> prices = Arrays.asList(1.00, 10.00, 100.00);
List<Double> pricesWithTax = Arrays.asList(1.22, 12.20, 120.00);

Then I tested like

public static void main(String[] args) throws IOException {
    Order order = new Order();
    double sum = order.sumBy(order::getPrices);
    double sumWithTaxes = order.sumBy(order::getPricesWithTax);
    System.out.printf("%.2f %.2f%n", sum, sumWithTaxes);
}

Outputs

111.00 133.42
0
On

I think the Supplier<T> functional interface is what you’re looking for:

Double sumBy(Supplier<Collection<Double>> supplier) {
  Collection<Double> prices = supplier.get();
}
0
On

Your 2 methods take no argument and return an object, so that fits the Supplier.get() method.

Don't use Double for the sum variable, since that will auto-box and auto-unbox way too much.

Method can be static since it doesn't use any fields or other methods of the class.

static double sumBy(Supplier<List<Double>> listGetter) {
    double sum = 0.0;
    for (double price : listGetter.get()) {
        sum += price;
    }
    return sum;
}

Better yet:

static double sumBy(Supplier<List<Double>> listGetter) {
    return listGetter.get().stream().mapToDouble(Double::doubleValue).sum();
}
0
On

Use Double sumBy(Supplier<List<Double>> doubles)