How to Pass a Function as a Parameter in Java

How to pass a function as a parameter in Java?

Java 8 and above

Using Java 8+ lambda expressions, if you have a class or interface with only a single abstract method (sometimes called a SAM type), for example:

public interface MyInterface {
String doSomething(int param1, String param2);
}

then anywhere where MyInterface is used, you can substitute a lambda expression:

class MyClass {
public MyInterface myInterface = (p1, p2) -> { return p2 + p1; };
}

For example, you can create a new thread very quickly:

new Thread(() -> someMethod()).start();

And use the method reference syntax to make it even cleaner:

new Thread(this::someMethod).start();

Without lambda expressions, these last two examples would look like:

new Thread(new Runnable() { someMethod(); }).start();

Before Java 8

A common pattern would be to 'wrap' it within an interface, like Callable, for example, then you pass in a Callable:

public T myMethod(Callable<T> func) {
return func.call();
}

This pattern is known as the Command Pattern.

Keep in mind you would be best off creating an interface for your particular usage. If you chose to go with callable, then you'd replace T above with whatever type of return value you expect, such as String.

In response to your comment below you could say:

public int methodToPass() { 
// do something
}

public void dansMethod(int i, Callable<Integer> myFunc) {
// do something
}

then call it, perhaps using an anonymous inner class:

dansMethod(100, new Callable<Integer>() {
public Integer call() {
return methodToPass();
}
});

Keep in mind this is not a 'trick'. It's just java's basic conceptual equivalent to function pointers.

Java Pass Method as Parameter

Edit: as of Java 8, lambda expressions are a nice solution as other answers have pointed out. The answer below was written for Java 7 and earlier...


Take a look at the command pattern.

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample
{
public interface Command
{
public void execute(Object data);
}

public class PrintCommand implements Command
{
public void execute(Object data)
{
System.out.println(data.toString());
}
}

public static void callCommand(Command command, Object data)
{
command.execute(data);
}

public static void main(String... args)
{
callCommand(new PrintCommand(), "hello world");
}
}

Edit: as Pete Kirkham points out, there's another way of doing this using a Visitor. The visitor approach is a little more involved - your nodes all need to be visitor-aware with an acceptVisitor() method - but if you need to traverse a more complex object graph then it's worth examining.

How to pass a function as a parameter in java

Java 8 was shipped with enormous number of functional interfaces. You can use one of those to describe the expected function to be passed as parameter in your method.

In your case, for passing a function which excepts a single double parameter and applys a logic, use java.util.function.DoubleUnaryOperator:

static double foo(DoubleUnaryOperator fn){
double aNumber = 2.0;
return fn.applyAsDouble(aNumber);
}

And then create a lambda (or an object which implements DoubleUnaryOperator) and pass it to the foo method:

foo(d -> d * 3);

or

public class Fn implements DoubleUnaryOperator {
@Override
public double applyAsDouble(double d) {
return d * 3;
}
}

How to pass a function as an parameter to another function

No, you can't pass methods.

But there is a simple workaround: pass a Runnable.

void myFunction(boolean coondition, Runnable function)
{
if(condition) {
function.run();
}
}

and call it like this: (using the old syntax)

myFunction(condition, new Runnable() {
@Override
public void run() {
otherFunction();
}
});

or using the new lambda syntax in Java 8 (which is mostly shorthand for the above):

myFunction(condition, () -> {otherFunction();}}

Pass function as parameter to Lambda java 8

You can pass the Predicate used in the filter right to the method which is the only thing that differs in the methods.

Assuming offer.getOfferRows() returns List<OfferRow>, then:

public String getAllDangerousProductsName(Offer offer, Predicate<OfferRow> predicate) {
return offer.getOfferRows().stream()
.filter(predicate)
.map(row -> row.getItemInformation().getOfferTexts().getName())
.collect(Collectors.joining(","));
}

Usage becomes fairly simple:

// using lambda expression
String str1 = getAllDangerousProductsName(offer, row -> row.isDangerousGood());
String str2 = getAllDangerousProductsName(offer, row -> row.isBulkyGood());
// using method reference
String str1 = getAllDangerousProductsName(offer, OfferRow::isDangerousGood);
String str2 = getAllDangerousProductsName(offer, OfferRow::isBulkyGood);

how to pass a function parameter in Java 8 in stream groupby

Take a look at the documentation for groupingBy.

You need a Function<? super T,? extends K> classifier as the type, or something more specific depending on how your ReportProfitAnalysis and reportProfitResult look.

For example:

private void MapResult(Function<? super ReportProfitAnalysis, ?> func) {   
reportProfitResult = reportProfits.stream()
.collect(Collectors.groupingBy(func));
}

You can pass the grouping function

Function<? super ReportProfitAnalysis, ?> func = ReportProfitAnalysis::getStatisticTime;

Note that the reportProfitResult here would be defined as Map<?, List<ReportProfitAnalysis>> reportProfitResult

How to pass a function as parameter in java to run it multiple times

You could try reflection here:

E.g:

public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {

Method method = Test.class.getMethod("myFunction");

boolean didwork = retry(method, 5);
if (didwork) {
System.out.println("I found my stuff");
} else {
System.out.println("I didn't found my stuff");
}

}

public static boolean retry(Method method, int loopTry)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {

boolean success = false;
for (int i = 0; i < loopTry; i++) {
success = (Boolean) method.invoke(null);
if (success) {
break;
}
}
return success;
}

public static boolean myFunction() {
boolean found = false;

//do stuff
if(stuff){
found = true;
}

return found;
}


Related Topics



Leave a reply



Submit