Issue
here's how lambdas are in kotlin -
val myLambda: (Int, Int) -> Unit = { a, b ->
Log.d(TAG, "sum value = ${a + b}")
}
myLambda(1, 2)//running the lambda
In java, I found these two methods to do the same.
Here, I can't have the runnable take a parameter.
// runnable method
Runnable runnable = () -> {
System.out.println("x");
};
runnable.run();
The issue with this method is I would have to declare multiple interfaces for different types
// interface method
Finder finder = (s1, s2) -> s1.indexOf(s2);
System.out.println(finder.find("1234", "23"));
public interface Finder {
public int find(String s1, String s2);
}
So, the question I have is whether there is an easier way to implement lambda in java better that both of these.
Note - I'm new to java.
Solution
Contrary to Kotlin, Java isn't a Functional programming language, it's Object-oriented and in addition has a moderate subset of functional features. On the other hand, Kotlin fully supports both Functional and Object-oriented paradigm.
In Kotlin, we can define a function, for instance like this:
val printSquare = { i: Int -> println(i * i) }
And its type would be successfully inferred, the part on the right would be recognized as being of a function type. Kotlin would know that it has operator invoke()
which can be used implicitly or explicitly printSquare.invoke(10)
.
Conversely, in Java something like that would not compile:
var printSquare = (int i) -> System.out.println(i * i); // compiler would not be able to infer the type `printSquare` becuase lambda expression by itself has no type
In Java, there's no function types. Instead, we have a notion of a functional interface.
Functional interface - is an interface which declares a single abstract
method (it might also have a bunch of static
and default
methods, but abstract
method should be only one). And every lambda expression or method reference should conform to a particular functional interface, i.e. they have no type by itself, they have to provide an implementation to the interface which would be the target type of lambda (or method reference).
To make the definition of printSquare
lambda shown above compile, we to provide the type (which should be a functional interface) and target type of the lambda would be inferred from the assignment context:
IntConsumer printSquare = i -> System.out.println(i * i);
For more information on the type inference in Java, see
Possible ways to interact with Java 8 function would depend on its target type. On printSquare
we can invoke accept()
and andThen()
(andThen
is a default method). With Runnable
we would have only run
at our disposal.
So the key point is that there are no functional types in Java, and in order to define a Java 8 function either as lambda or method reference we need either:
Define our own functional interface which would be a target type for the lambda;
Use existing functional interface from JDK, some kind of library, or framework.
The following Kotlin function:
val myLambda: (Int, Int) -> Unit = { a, b ->
Log.d(TAG, "sum value = ${a + b}")
}
can be translated into Java as a BiConsumer:
BiConsumer<Integer, Integer> myLambda = (a, b) -> Log.d(TAG, "sum value = " + (a + b));
The issue with this method is I would have to declare multiple interfaces for different types
Well, it's actually rarely the case when you need to declare a functional interface. Only in the package java.util.function
there are over 40
functional interfaces at your disposal. And also there are lots and lots of them in other parts of the JDK, the most common are Comparator
, Runnable
, Callable
, etc.
And there are numerous functional interfaces provided by frameworks. Because the ability to implement some functionality with a single line of code makes a life a bit easier, and because some interfaces naturally became lean when their designers respect the Interface segregation principle.
Remember that any interface, even it has been designed prior to Java 8, if it has exactly one abstract method is a functional interface, and therefore eligible to be implemented using lambda.
Answered By - Alexander Ivanchenko
Answer Checked By - Terry (JavaFixing Volunteer)