Java lambdas
I’m not a java person. I’ve never used it in production, nor have I spent any real time with it outside of my professional work. However, when a language dawns upon lambdas I am drawn to try out their implementation. I’ve long since despised Java for the reasons of verbosity, lack of real closures or events, type erasure in generics, and an over obsession with anonymous classes, so I’ve shied away from doing anything in it.
Still, at least the Java world is trying. While I’d love to just ignore the fact that Java exists, I can’t. Lots of interesting projects are done in Java, and a lot of world class tools are written in Java, so from a professional standpoint it’d be good for me to know it.
In the past when I looked into how past Java utilities did “functional” it never felt natural to me. People have suggested LambdaJ or google’s Guava, but Guava even goes so far to say to not use their functional approach. LambdaJ’s is just as verbose as anything else, and in benchmarks its shown to be at least 2 times slower! Not a good sign.
But the coming of Java 8 I think a lot of these problems will be solved. Not to mention I’m sure that projects such as RxJava are ecstatically waiting for this since it will make their (and any other reactive users) lives a whooole lot better.
Anyways, I present to you my first Java program in 5 years:
import java.util.List;
import java.util.concurrent.ExecutionException;
import static java.util.Arrays.asList;
public class Main{
public static void main(String[] arsg) throws InterruptedException, ExecutionException {
List\<String\> strings = asList("foo", "bar", "baz");
strings.forEach(System.out::println);
ThreadUtil.queueToPool(() -\> {
System.out.println("In the damn thread");
return "foo";
}).get();
System.out.println("done");
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadUtil{
private static final ExecutorService \_threadPoolExecutor = Executors.newCachedThreadPool();
public static Thread run(Runnable r){
Thread thread = new Thread(r);
r.run();
return thread;
}
public static Future\<?\> queueToPool(Callable\<?\> r){
return \_threadPoolExecutor.submit(r);
}
}
The program does nothing useful. I just wanted to see what it was like to write some java lambda code, and I was pleasantly surprised. Even though lambda’s in Java 8 aren’t actually first class functions, but are in fact wrappers on interfaces that are tagged with the @FunctionalInterface
attribute. For example, look at Supplier
(which is analgous to Action
in C#, i.e a function with no arguments that when executed returns a value)
@FunctionalInterface
public interface Supplier\<T\> {
/\*\*
\* Gets a result.
\*
\* @return a result
\*/
T get();
}
Java’s lambda magic looks to rely on the fact that if an interface has the attribute, then it can be auto converted into a lambda as long as there is only one function that is not implemented. You could, however, treat the interface the old fashioned java way: create an anonymous class that implements get
and execute .get(). Still, why would you want to?
To demonstrate the interface to function mapping you can see both the new way and the old way of doing the same things
Supplier\<String\> newWay = () -\> "new way";
Supplier\<String\> oldWay = new Supplier\<String\>() {
@Override
public String get() {
return "old way";
}
};
My only gripe here is that the supplier is still an interface. It’s not a first class function, meaning I can’t just execute newWay()
. I have to do newWay.get()
which seems stupid at first. But, there is a reason.
The reason is that you can now have default
implementation in interfaces, meaning that you can create an interface instance that has a bunch of stuff defined but create one off lambda overrides of another method. This is pretty neat. Look at this example:
@FunctionalInterface
public interface TestMethods{
public void doWork();
default void doOtherWork(){
System.out.println("do other work default method");
}
}
Now I can either do the old fashioned way (creating an anonymous class and implementing doWork
) or I can create an instance that is assigned a lambda, which does the same thing:
TestMethods m = () -\> System.out.println("creating the do work method at instantation");
m.doWork();
m.doOtherWork();
If you have more than one undefined method in a functional interface the compiler will bitch at you, rightfully so.
Anyways, it looks like the Java world is finally growing up!