Two years ago, I blogged about parallel for each construct using a very early version of lambda prototype compiler. At that time, Data Parallelism was already available in C# TPL, but Java designers were hard at work in bringing this idiom to Java.

Lambda expressions support in Java 8 is here for everyone to give it a spin. Functional touch to Collections library makes it a breeze to program in Java. you get this one-liner using Java 8 Stream API.

There are more such one-liners you can think of using parallel constructs in Java 8. Here is another teaser, send an email blast to all customers.

Streams API brings several of the LINQ as well as PLINQ awesomeness to Java Collections library. Here is an adhoc query over a collection using the new Streams API.

Check it out here for more one-liners. You may want to checkout this article that compares LINQ with Java Streams API. While, there are constraints with the Java Streams proposal, it hits the right balance and there is a pedagogical value to it as well, keeping majority Java developers happy.

Enjoy!

Possibly Related Posts:


Almost a year later since publishing the original Lambda proposal, JSR 335 EG has finally decided to adopt C# style syntax for Java 8 Lambda expressions. Brian has outlined the formal model for the new C# style syntax in his mail to lambda-dev:

lambda = ArgList Arrow Body
ArgList = Identifier
| “(” Identifier [ “,” Identifier ]* “)”
| “(” Type Identifier [ “,” Type Identifier ]* “)”
Body = Expression
| “{” [ Statement “;” ]+ “}”

Last week, Maurizio has pushed an updated compiler implementation that aligns with this new C# style syntax. I basically converted the Lambda examples used in my original post which I wrote an year ago when the initial straw-man syntax was prototyped. This post is essentially a take2, that illustrates Lambda expressions with the new C# style syntax and covers the latest developments in Lambda community. Honestly speaking, I enjoyed using the new syntax as part of this exercise. Enjoy!

Lambdas are available in the form of anonymous inner classes in Java. Anonymous inner classes are a form of nested classes that has no name and exhibits the following behavior as detailed in JLS 15.9.5.

  • An anonymous class is never abstract
  • An anonymous class is always an inner class; it is never static
  • An anonymous class is always implicitly final

One common use of anonymous inner classes is to create function objects in Java on the fly. [Refer Item 21 in Effective Java 2nd Edition pg 103]

Let us look at sorting an array of strings based on its length using an anonymous Comparator instance.

        String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
        Arrays.sort(teams, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

To create process objects, such as Runnable, Thread, or TimerTask instances.

        final ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("I am Runnable");
            }
        });

Anonymous classes have many limitations as outlined in Item 22 in Effective Java 2nd Edition [pg 108]. With Lambda expressions, you should be able to rewrite these samples more concisely eliminating the bulky syntax that comes with anonymous inner classes :

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Sample1 {

  public static void main(String... args) {
    final ExecutorService executor = Executors.newCachedThreadPool();
    // assignment context
    Runnable task = () -> System.out.println("I am Runnable"); //take 1
    executor.submit(task);

    // method invocation context
    executor.submit(() -> {System.out.println("I am Runnable");}); //take 2
    executor.shutdown();
  }
}

Array sorting using a comparator with Lambda expressions is a one liner:

import java.util.Arrays;
import java.util.Comparator;

public class Sample2 {
	public static void main(String... args) {
		String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
		final Comparator<String> c = (s1, s2) -> s1.length() - s2.length();
		Arrays.sort(teams, c); //take 1
		Arrays.sort(teams, (s1, s2) -> s1.length() - s2.length()); //take 2
	}
}

So, what next? Let us do some hands-on with these Lambdas and explore what Lambdas has to offer for Java developers. I setup the new prototype on my Windows environment following Remi’s instructions. It was fairly straight forward (all you need is Mercurial Client, Apache Ant, and JDK 7).

Here is a simple build script (build.bat) I used in Windows, that you can place in the “make” sub-directory under “langtools” :

ant -Dboot.java.home=C:\jdk1.7.0 clean build

This would create classes.jar under “dist\lib” sub-directory. You need to place this jar in your classpath when using the prototype.

You can use the following batch scripts for compiling and running your Lambda examples (tested with the JDK 7 GA release).

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;. %1

It is required to include classes.jar in the classpath due to runtime dependencies that are not available in the binary build. To make sure if you are running the prototype compiler, the output should show “internal” tag:

C:\jdk8-lambdas\samples>javac.bat -version
javac 1.7.0-internal

Let us look at a simple example:

public class SimpleLambda {
  interface HelloWorld {
    void greet();
  }

  {
    HelloWorld greeting = () -> System.out.println("Hello World!");//nilary Lambda expression
    greeting.greet();
  }

  public static void main(String... args) {
    new SimpleLambda();
  }
}

To compile this example:

javac.bat SimpleLambda.java

To run this example:

java.bat SimpleLambda

Voila, you ran your first lambda example successfully if you see “Hello World!” output.

Let us look at another example which uses parameterized types in this case.

public class Sample3 {
  interface Squarer<X, Y> {
    Y square(X x);
  }

  public static void main(String... args) {
    Squarer<Integer, Integer> s = (x) -> x * x;// 1-ary Lambda expression
    System.out.println(s.square(5));
  }
}

In both these examples, you notice a pattern commonly referred to as single abstract method (SAM), defined using an interface with exactly one abstract method. This is a structural property identified by the compiler and it does not take into account methods inherited from java.lang.Object (as in java.util.Comparator).

For example, Runnable, Callable, etc belongs to this category of SAM types that can be converted in the context of assignment as shown below.

final Runnable task = () -> System.out.println(“I am Runnable”);

In this code, “task” is an Runnable instance, while the lambda expression () -> … is not. Only after conversion, the target type becomes an instance of that SAM type.

Syntax – The Holy Grail of Lambda

A lambda expression is written as a parameter list, followed by the -> token, followed by an expression or a statement block. In case of single line Lambda expression, return keyword can be omitted. Block of statements are surrounded with {} and if you need to return a result, you need to specify the return keyword.

Note ‘thin’ arrow is still used (instead of ‘fat’ (=>) arrow as used in C#). This is still under discussion. I personally like ‘thin’ arrow and ‘fat’ arrow does not really help visually.

Lambdas in Java exhibit the following behavior :

  • An interface with exactly one abstract method is referred to as an functional interface (fka SAM types).
  • Lambdas are not instances of classes.
  • Lambdas can only be converted to SAM interfaces.
  • SAM types are instances of classes.
  • Lambdas are lexically scoped.

Lambda definition (excerpt from draft)

A lambda expression e is convertible-to a SAM type S if an anonymous inner class that is a subtype of S and that declares a method with the same name as S’s abstract method and a signature and return type corresponding to the lambda expressions signature and return type would be considered assignment-compatible with S.

The return type and exception types of a lambda expression are inferred by the compiler; the parameter types may be explicitly specified or they may be inferred from the assignment context.

The type of a formal parameter can be omitted, in which case the compiler will infer a type from the target type of the lambda conversion. Let us see couple examples where the types are inferred by the compiler.

public class Sample4 {

  enum Decision {
    APPROVE, DECLINE, APPROVE_REFER
  }

  interface DecisionService {
    Decision getRiskDecision(Applicant applicant);
  }

  class Applicant {
    private int score;

    public Applicant(int score) {
      this.score = score;
    }

    public int getScore() {
      return score;
    }
  }

  public void test() {
    DecisionService cs = (a) -> {
    if (a.getScore() > 700) {
      return Decision.APPROVE;
    } else if (a.getScore() > 600 && a.getScore() < 650) {
      return Decision.APPROVE_REFER;
    } else {
      return Decision.DECLINE;
    }};
    Decision decision = cs.getRiskDecision(new Applicant(800));
    System.out.println(decision.toString());
  }

  public static void main(String... args) {
    new Sample4().test();
  }
}

In line #24 above, the type of the formal parameter Applicant is inferred by the compiler.

public class Sample5 {

  class Payment {
    private int amount;

    Payment(int amount) {
      this.amount = amount;
    }

    public int getAmount() {
      return amount;
    }
  }

  interface PaymentProcessor {
    void process(Payment pmt);
  }

  public void test() {
    invokeProcessor((pmt) -> log("Processed # " + pmt.getAmount() + " at " + new Date()));
  }

  void invokeProcessor(PaymentProcessor processor) {
    processor.process(new Payment(42));
  }

  void log(String message) {
    System.out.println(message);
  }

  public static void main(String... args) {
    new Sample5().test();
  }
}

In line #20, the type of the formal parameter Payment is inferred by the compiler.

Here is the definition of SAM and non-SAM types as explained in one of the Lambda test case.

SAM types:
1. An interface that has a single abstract method
2. Having more than one distinct methods, but only one is “real”, the others are overriden public methods in Object – example:

Comparator<T>

3. Having more than one methods due to inheritance, but they have the same signature
4. Having more than one methods due to inheritance, but one of them has a subsignature of all other methods

    a) parameter types compatible
    b) return type substitutable
    c) thrown type not conflicting with the thrown clause of any other method
    d) mixed up

5. Type-dependent SAM types

non-SAM types:
6. An interface that has a single abstract method, which is also public method in Object
7. Having more than one methods due to inheritance, and none of them has a subsignature of all other methods

What has changed since then in the Lambda community?

Well, the first thing that happened in the past year was the formation of expert groups; JSR 335 for Lambda support in Java 8 and JSR 337 umbrella JSR for Java 8. Two polls were conducted in June on lambda-dev mailing list and the results mostly favored BGGA style syntax. Choosing the syntax that C# and Scala broadly share is a wise move by the JSR 335 EG. Did any one catch up with the replacement term for SAM? It is called “functional interface”, although SAM is widely popular among lambdaphiles.

Virtual extension methods approach was revised since the original strawman proposal. Brian explains this beautifully from conception to implementation in this paper Interface evolution via virtual extension methods. Virtual extension methods will be implemented as a VM feature, which makes it transparent like any other method invocation for non-Java languages. The following JVMLS talks explain the latest developments in virtual extension methods and lambda implementation strategies. I strongly encourage to watch them as it is the only source of information for people outside the JSR 335 Expert Group.


[Photo credit: http://www.lumaxart.com/]

Possibly Related Posts:


Last November, Mark Reinhold announced that Closures will be added to the Java language and six months later we had an initial prototype based on the Straw-Man proposal and last month’s update was considered a significant progress for the language in years. As mentioned in Mark’s post, “Working with parallel arrays in Java, unfortunately, requires lots of boilerplate code to solve even simple problems. Closures can eliminate that boilerplate.” In my earlier post, I discussed how Lambda expressions make Aggregate operations a breeze to work with in Java. But, we still lack parallel looping constructs such as parallel for, foreach APIs that would take advantage of the multi-core machines we have today.

In this next Lambda adventure, I will be revisiting the Parallel ForEach example discussed by Howard in his “New Control Structures for Java” post, where he explains the use of anonymous inner classes to map a function that executes in parallel and retains the order of the original map, handles exceptions and implements continue operation. Here is the anonymous inner class version of the code:

The program produces the below output:

{1=H, 2=e, 3=l, 4=l, 5=o}

Now, that we have a working Lambda prototype, this code could be modified to take advantage of Lambda expressions. Let us enable the Lambda finder option in the compiler that identifies potential candidates for converting an anonymous inner class instance to an Lambda expression. Here is the updated javac.bat used to run with the latest prototype compiler.

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main -XDidentifyLambdaCandidate=true %1

Compiling Parallel.java with this hidden compiler option identifies 2 candidates for Lambda expressions.

C:\JDK7\lambda\samples&gt;javac.bat Parallel.java
Parallel.java:16: Note: This anonymous inner class creation can be turned into a lambda expression.
            return new Callable&lt;O&gt;() {
                                     ^
Parallel.java:70: Note: This anonymous inner class creation can be turned into a lambda expression.
        final ForEach&lt;Character, Integer, Character&gt; trim = new ForEach&lt;Character, Integer, Character&gt;() {
C:\JDK7\lambda\samples&gt;

Let us quickly refactor Howard’s code using Lambda expressions and here is my take.

This version does not significantly change from its anonymous counterpart, it reduces at most 10 lines of code. But, it introduces two important concepts in addition to use of Lambda expressions. Lines 6 and 13 uses the new exception transparency mechanism and Line 62 shows how lexical scoping makes Lambda expressions different from anonymous inner classes.

Exception Transparency

Exception transparency is a new feature proposed as part of the umbrella Lambda proposal. While this feature is not required to support Lambda expressions, it is useful in library implementations that require abstraction over generic exceptions. Java Generics does a decent job at abstracting over method return types and argument types, leaving abstraction over types of checked exceptions in limbo. This makes it difficult for libraries to support generic exception types in APIs. The two extreme cases where libraries usually model their exception types are :

In case of Runnable, the run() method throws nothing.

public interface Runnable {
    public abstract void run();
}

In case of Callable, the call() method throws everything.

public interface Callable<V> {
    V call() throws Exception;
}

As more and more libraries would take advantage of executing Lambda expressions as a block of code, the inability to generify thrown exception types makes this proposal a compelling use case.

A throws type parameter is a generic type parameter that is introduced with the keyword throws; throws type parameters implicitly have an upper bound of Exception (though any upper bound that is a subtype of Throwable may be explicitly specified) and can correspond to zero or more actual types that are subtypes of the upper bound.

With this support in the language, we should be able to abstract generic exception types:

	interface Block<throws E> {
		public void execute() throws E;
	}

Lexical scoping

Unlike anonymous inner classes, lambda expressions are lexically scoped. This means that code inside the Lambda body sees only what is available immediately outside the lambda expression. For instance, access to names from inherited classes/interfaces is not allowed as seen in Line #62 of our example above.

I wanted to briefly touch upon these concepts that are relevant to our discussion. Please refer to the proposal for more details.

.NET world

Let us look at how modern languages support Parallelism in their libraries. Here is an closest example using C# Task Parallel Library (TPL) (from Patterns of Parallel Programming Guide).

But this is just an attempt if someone wanted to write their own parallel foreach construct using existing C# APIs. But, this is not required. In C#, parallel constructs are available for a while now. Using the Parallel.ForEach construct in TPL, iterating all the Test records of a Student and calculate the GPA would look something like:

Fair enough, this construct is concise and abstracts all the machinery from the Client code. Are we close enough to get a similar construct in Java? I think so, we do have parallel collections library that supports parallelism using Fork-Join framework today. It looks like Doug Lea has recently revealed his plans for developing new library components for parallel operations on aggregates (collections and arrays) for JDK8 (based on proposed language support for lambdas). I believe this effort would produce these constructs in Java.

For the sake of fun, I compiled the extry166y sources with the compiler option “-XDidentifyLambdaCandidate=true”, it identified 168 candidates that can be turned into a lambda expression. Less code means more fun and you see that for real.

Update (6/11/2011) : Updated the Parallel class (Lambda version) to compile with the latest lambda prototype compiler. Abstract classes with single abstract method are no longer considered valid SAM types as per the revised rules.

Possibly Related Posts: