Ravindra babu
Ravindra babu

Reputation: 38950

Scala -> Java , Pass function as a parameter to another function

I am exploring both scala and Java 1.8 but unable to find equivalent code in with java 1.8 lambda expressions.

Scala code:

object Ex1 extends App {

  def single(x:Int):Int =x
  def square(x:Int):Int = x * x
  def cube(x:Int):Int = x*x*x

  def sum(f:Int=>Int,a:Int,b:Int):Int=if (a>b) 0 else f(a) + sum(f,a+1,b)

  def sumOfIntegers(a:Int,b:Int)=sum(single,a,b)
  def sumOfSquares(a:Int,b:Int)=sum(square,a,b);
  def sumOfCubes(a:Int,b:Int)=sum(cube,a,b);

  println(sumOfIntegers(1,4));
  println(sumOfSquares(1,4));
  println(sumOfCubes(1,4));

}

output:

10
30
100

java:

public class Test1{
    public int single(int x){
        return x;
    }
    public int square(int x){
        return x * x;
    }
    public int cube(int x){
        return x * x * x;
    }
    // what's next? How to implement sum() method as shown in Scala?
    // Stuck in definition of this method, Stirng s should be function type.
    public int sum( Sring s , int a, int b){
        // what will go here?
    }
    public int sumOfIntegers(int a, int b){
        return sum("single<Function> how to pass?",a,b);
    }
    public int sumOfSquares(int a, int b){
        return sum("square<Function> how to pass?",a,b);
    }
    public int sumOfCubes(int a, int b){
        return sum("cube<Function> how to pass?",a.b);
    }
}

Is it possible to achieve the same with JDK 1.8?

Upvotes: 1

Views: 1337

Answers (4)

Michael Lloyd Lee mlk
Michael Lloyd Lee mlk

Reputation: 14661

You are going to need to define the methods that you are going to use. The only one that comes with Java is the Function<X,Y> which (with Integer) can be used for single, square and cube and BiFunction<T,Y, R> which can be used for the three sumOfs.

interface Sum {
    Integer apply(Function<Integer, Integer> func, int start, int end);
}

The single, square and cube could be either methods in the class (see cube or inline (see the other two). They are Fuctions. This function can then be passed to other methods and called with variableName.apply.

  class Test
{
    private static Integer sum(Function<Integer, Integer> func, int a, int b) {
        if (a>b)
            return 0;
        else return func.apply(a) + sum(func,a+1,b);
    }

    private static Integer cube(Integer a) {
        return a * a * a;
    }

    public static void main (String[] args) throws java.lang.Exception
    {

        Function<Integer,Integer> single = a -> a;
        Function<Integer,Integer> square = a -> a * a;
        Function<Integer,Integer> cube = Test::cube;

        // You can not do the sum in-line without pain due to its recursive nature.
        Sum sum = Test::sum;

        BiFunction<Integer, Integer, Integer> sumOfIntegers = (a, b) -> sum.apply(single, a, b);
        BiFunction<Integer, Integer, Integer> sumOfSquares = (a, b) -> sum(square, a, b); // You could just use the static method directly. 
        BiFunction<Integer, Integer, Integer> sumOfCubes = (a, b) -> sum(cube, a, b);

        System.out.println(sumOfIntegers.apply(1,4));
        System.out.println(sumOfSquares.apply(1,4));
        System.out.println(sumOfCubes.apply(1,4));
    }


}

Upvotes: 1

Alexey Romanov
Alexey Romanov

Reputation: 170839

In Java 8 you can use any functional interface, i.e. an interface with exactly one non-static method without a default implementation, in place of Scala's Function<N> types. There are quite a few such interfaces in the java.util.function package, for single-argument and two-argument functions; in particular for functions which take and return int you should use IntUnaryOperator, already mentioned in other people's comments. If you have more than two arguments, or two arguments of different types, define your own interface with one method. E.g. for functions of 3 arguments which take int, long and long and return a non-primitive:

interface Fun3ILLO<T> {
    public T apply(int arg1, long arg2, long arg3);
}

(obviously you can choose the interface and method name you want).

Upvotes: 1

VDanyliuk
VDanyliuk

Reputation: 1049

Function<Integer, Integer> single = x -> x;
Function<Integer, Integer> square = x -> x*x;

public int sum( Function<Integer, Integer> s , int a, int b){
    if (a>b){
        return 0;
    } else {
        s.apply(a) + sum(s,a+1,b)
    }
}

Upvotes: 1

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

Reputation: 18865

Yes, it is possible:

 public Integer sumSingle(Integer a) { return a; }

 public int sum(Function<Integer, Integer> f, int a, int b)
 {
      ... : f.apply(a+1); // or whatever
 }

 public int sumOfIntegers(int a, int b)
 {
     return sum(Test1::single, a, b);
 }

The construct Class::method creates a Function object from the method. Or if you don't need to reuse it, you can directly pass an argument instead: (Integer a) -> a*a* ...

Upvotes: 1

Related Questions