Home > Enterprise >  Method declaration with a function to extract fields of an object and a binary operator which will b
Method declaration with a function to extract fields of an object and a binary operator which will b

Time:06-13

Given the following sample class Foo

@Getter
@AllArgsConstructor
@ToString
static class Foo {
    int field1;
    int field2;
    String field3;
}

I want to declare a method, let's call it applyBinOperator, which accepts two Foo objects a key-extractor and a binary operator and apply that operator to the extracted fields of the Foo objects and returns the result. So basically I want to call the method in the following way or something similar:

Foo foo1      = new Foo(10, 20, "first");
Foo foo2      = new Foo(100, 200, "second");

int sum       = applyBinOperator(foo1, foo2, Foo::getField1, (a,b) -> a b);

int prod      = applyBinOperator(foo1, foo2, Foo::getField2, (a,b) -> a*b);

String concat = applyBinOperator(foo1, foo2, Foo::getField3, (a,b) -> String.join(a,b));

//and get sum = 110, prod = 4000 and concat = firstsecond 

But I am struggling to find the correct syntax to define the method since I am not very familiar with generics. I have tried the following but it doesn't compile yet:

public  static <T> T applyBinOperator(Foo foo1, Foo foo2, 
       Function<? super T, ?> keyExtractor, BinaryOperator<T> binaryOperator) {

    return binaryOperator.apply(keyExtractor.apply(foo1), keyExtractor.apply(foo2));
}

Can someone help me with the correct syntax?

CodePudding user response:

You seem to have just mixed up the order of the type parameters of Function. To write "a function that takes a Foo and returns a T", it is Function<Foo, T>:

public  static <T> T applyBinOperator(Foo foo1, Foo foo2,
                                      Function<Foo, T> keyExtractor, BinaryOperator<T> binaryOperator) {
    return binaryOperator.apply(keyExtractor.apply(foo1), keyExtractor.apply(foo2));
}

We can make the Foo part generic too, and also apply PECS:

public  static <T, U> T applyBinOperator(U foo1, U foo2,
                                      Function<? super U, ? extends T> keyExtractor, BinaryOperator<T> binaryOperator) {
    return binaryOperator.apply(keyExtractor.apply(foo1), keyExtractor.apply(foo2));
}

Also, String.join does not join "first" and "second" together. You probably meant String.concat, or just use , which works with strings too.

  • Related