Core Java

Java 8: Testing the Lambda Water

Java 8 is about a year away and comes with a language feature I really look forward to: Lambda Expression. Sadly the other big feature, Modules for the Java Platform, has been delayed to Java 9. But nevertheless, bringing lambda expressions (or closures if you like) into the language will make programming in Java much better.

So nearly one year to go – but as Java is developed open source now, we can have a look and try to use it right now. So let’s go!

Download and Install Lambda enabled Java 8

First, I expected that I have to compile Java 8 myself, as it has not yet been release. But I was pleasantly surprised to see, that there are binary build available for all platforms at http://jdk8.java.net/lambda/. So I just downloaded the latest developer preview build and installed it on my computer.

To make sure it works, I created an LambdaIntro class containing a “Hello, World!”, compiled and executed it:

~ $ export JAVA_HOME=~/Devtools/Java/jdk1.8.0/
~ $ cd spikes/lambda-water
~ $ $JAVA_HOME/bin/javac  src/net/jthoenes/blog/spike/lambda/LambdaIntro.java
~ $ $JAVA_HOME/bin/java -cp src net.jthoenes.blog.spike.lambda.LambdaIntro
Hello from Java 8!

Note: I use the command-line to compile and execute here, because IDEs do not support Java 8 as of now.

The Non-Lambda Way

As an example lets assume I want to loop through a list of objects. But for my business logic, I need to have the value and the index of the list item. If I want to do it with current Java, I have to handle the index together with the actual logic:

List list = Arrays.asList('A', 'B', 'C');
for (int index = 0; index < list.size(); index++) {     String value = list.get(index);     String output = String.format('%d -> %s', index, value);
    System.out.println(output);
}

This will output

0 -> A
1 -> B
2 -> C

This is not too bad, but I did two things in the same few lines of code: controlling the iteration and providing some (very simple) business logic. Lambda expressions can help me to separate those two.\

The eachWithIndex method signature

So I want to have a method eachWithIndex which can be called like this:

List list = Arrays.asList('A', 'B', 'C');
eachWithIndex(list,
    (value, index) -> {
        String output = String.format('%d -> %s', index, value);
        System.out.println(output);
    }
);

The method receives two parameter. The first one is the list and the second one is a lambda expression or closure which instructs the method what to do with each list item. As you can see in line 3, the lambda expression receives two argument: the current value und the current index. These arguments do not have a type declaration. The type information will be inferred by the Java 8 compiler. After the arguments, there is a -> and a block of code which should be executed for every list item.

Note: You will have to write this method in a normal text editor or ignore the error messages inside your IDE.

Implement the eachWithIndex method

To use a lambda in Java 8, you need to declare a functional interface. A functional interface is an interface which has exactly one method – the method which will be implemented by the lambda expression. In this case, I need to declare a method which receives an item and an index and returns nothing. So I define the following interface:

public static interface ItemWithIndexVisitor<E> {
    public void visit(E item, int index);
}

With this interface I can now implement the eachWithIndex method.

public static <E> void eachWithIndex(List<E> list, ItemWithIndexVisitor<E> visitor) {
    for (int i = 0; i < list.size(); i++) {
         visitor.visit(list.get(i), i);
    }
}

The method makes use of the generic parameter <E>, so the item passed to the visit method will be inferred to be of the same type than the list.

The nice thing about using functional interfaces is, that there are a lot of them already out there in Java. Think for example of the java.util.concurrent.Callable interface. It can be used as a lambda without having to change the code which consumes the Callable. This makes a lot of the JDK and frameworks lambda enabled by default.

Using a method reference

One little handy thing coming from Project Lambda are method references. They are a way, to re-use existing methods and package them into a functional interface object. So let’s say I have the following method

public static <E> void printItem(E value, int index) {
    String output = String.format('%d -> %s', index, value);
    System.out.println(output);
}

and I want to use this method in my eachWithIndex method, than I can use the :: notation inside my method call:

eachWithIndex(list, LambdaIntro::printItem);

Looks nice and concise, doesn’t it?

Summary

This makes my first lambda example run. I couldn’t avoid a smile on my face to see closures running in one of my Java program after longing for them so long. Lambda Expression are currently only available as a developer preview build. If you want to find out more, read the current Early Draft Review or go to the Project Lambda project page.

I uploaded the full example code to gist.

Reference: Java 8: Testing The Lambda Water from our JCG partner Johannes Thoenes at the Johannes Thoenes blog blog.

Johannes Thones

Johannes is a Software-Developer, ThoughtWorker, Permanent Journeyman, Ruby Enthusiast, Java and Devils Advocate. He lives and works in Hamburg, Germany.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Zed
Zed
11 years ago

This would be one line in java 8 (:p)
list.forEach((item)-> System.out.println(String.format(“%d -> %s”, list.indexOf(item),item)));

Back to top button