Lambda Expression

Table of contents
Reading Time: 7 minutes

As a Java developer, it becomes your need to study about the new concepts and APIs keeps popping in and learn them to apply it in your development and compete the world. One of the biggest changes in Java 8 is Lambda Expressions. Nowadays several JVM based Programming Languages like Groovy, Ruby and Scala etc. keeps talking about how much functional they are and how much concised code they write, just keeps praising about the features. And hence come the Java feature which helps making more functional Applications in Java and much more than that i.e. Lambda Expressions.

1. What is Lambda Expression?

Lambda is a new programming construct, which lets you write Java applications in a completely different paradigm from the traditional Obejct Oriented Programming. I will be giving a quick overview of what is Lambda? Why should we use it? How to use it? Lambdas under the hood and how Lambda has simplyfied Java APIs and their use.

A lambda expression is an annonymous function. Whenever a single abstracted method Interface is expected or we need to have a function which should be loaded dynamically into the memory we can go for Lambda. There may be many other more correct definitions to it but this is what I understood after studing Lambda. Take a look at the fuction below:

public class DemoLambda {

	public static void main(String... a) {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(a[0] + " : from New Thread");
			}
		});
		thread.start();
		System.out.println(a[0] + " : from main Thread");
	}
}

$java DemoLambda “Hello Lambda!!!”
Hello Lambdas!!! : from main Thread
Hello Lambdas!!! : from New Thread

Well, run method has four main things

  • Returrn Type -> void

  • Name -> run

  • Parameter List -> blank (in this case)

  • Body

From above four things, if we observe deeply, we can deduce that the most important part is body of the function. The body of the function is the area where we do the whole business logic. The second most important deduction is the Parameter list, we can’t know what to do in body without knowing what to be manipulated.

2. How to Use Lambdas?

Means the Return Type ( As it can be inffered ) and the Name of the fuction are just ceremonies. We can do things with an annonymous functions.

So, this is how we can do the above thing with lambdas:

public class DemoLambda {

	public static void main(String... a) {
		Thread thread = new Thread(
			()->System.out.println(a[0] + " : from New Thread"));
		thread.start();
		System.out.println(a[0] + " : from main Thread");
	}
}
$java DemoLambda “Hello Lambda!!!”
Hello Lambdas!!! : from main Thread
Hello Lambdas!!! : from New Thread

So, you see the beauty now, the beauty of Java and its APIs. You must have noticed one more thing that Lambda expression supported an API, Thread, which is existing with us from all the the way Java has found. Means, Lambda also supports Backward Compatiblity. Well, that’s what all Java APIs do. Java Always supports its existing APIs with the new one without changing the existing APIs. You can use Lambda expressions instead of using inner classes anywhare a single abstracted method Interface is expected.

3. How Lambdas are implemented?

Well, we must be curious how Lambdas are implemented under the hood? I mean, from the above example all of you must have got a thought that “Oh! Okay, so there must be some Anonymous inner class created by the compiler at the run time for implementing Lambda!”. Well, it appears as instead of passing anonymous inner class you could pass a Lambda.

Thread thread = new Thread(()->System.out.println(a[0]));
thread.start();

The above code gives a perception that it may be using some anonymous class internally by the compiler 

Thread thread = new Thread(new Runnable() {
  @Override
  public void run() {  System.out.println(a[0]);  }
}

What is shown in above analogy is our expectation. But wait I’m going to show magic here, only this must not be the reason of your happiness as a programmer. Let me take you beyond this.

If you talk about other JVM based languages like Groovy, Ruby or Scala, all there syntactic work is internally handled by compiler. Means if you will make the same example in Scala its compiler will create an inner anonymous class under the hood to implement its syntactic sugar which seems attractive to you.

val list = List(3,4,5)
list.foreach( a => println(a))
$ scala A.scala 
3
4
5

Wow, In scala it was like magic No Class, No method, No Compilations. Just written two lines and got the required output.
But when I decompile the above executed code it shows :

A.scala
Main$.class
Main.class
Main$$anon$1.class
Main$$anon$1$$anonfun$1.class

Scala had been doing it till scala 2.2. You would say “Yeah, I was right Java must be following the same because all of other JVM based laguages are doing it”. Let’s wait and watch!

The more annonymous inner classes you create the more annonymous objects you have on the disk and hence big jar files. The bigger jar files, it will take more time to load, more time it takes. Once it’s loaded into JVM a large number of annonymous classes and there object are create when the JVM runs it and hence more Garbage. Just for second, think about the scene where the villain (Out memory Exceptions, Stackoverflow errors etc.) comes and destroys your world, where we may have a situation in which millions of inner annonymous classes are being created by the compiler and their objects left to be collected by GC.

I doubt your level of happiness after seeing that, felt like betrayed to me when I saw this.

Java being in industry for more than 20 years, Java has a BIG fan following ( more than 9 million programmers all around the world ). So, It would not suit Java doing the same thing what today’s youngsters doing. Because when 9 million programmers use your language you can’t just simply follow the new trends, you must be coming up with something different.

So, just go and study the javap -c output of you program once, you will see a magical method called behind the scene of lambdas i.e. invokedynamic. And no anonymous inner classes.

class A {
  A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public static void main(java.lang.String...);
    Code:
       0: new           #2                  // class java/lang/Thread
       3: dup
       4: aload_0
       5: invokedynamic #3,  0              // InvokeDynamic #0:run:([Ljava/lang/String;)Ljava/lang/Runnable;
      10: invokespecial #4                  // Method java/lang/Thread."":(Ljava/lang/Runnable;)V
}

 Java has been providing this method to all dynamically typed languages, but used it first time in the implementation of Lambda Expressions. Invokedynamic method implicitly called by the compiler and there are three possibilities your Lambda can become, a static method (depending upon the context), an instance method or a routing of invokedynamic to an existing method in another class. Wasn’t that a magic? You didn’t even need to think about what memory or Garbage Collector time its gonna take, and your task is done without any memory footprints.

That’s what I call WOW! I will keep it somewhat lengthy in present instead of of unhealthy in future. As simple as that.

4. Getting rid of External Iterations using Lambdas!

Here we will see how we can get rid of, imperative style to functional Style, for External Iterations. Below you see an example of imperative style of external iteration, where we need to control initial condition of index, upper-bound of index and then the increment in the index, then print the value at index. This type of iteration adds very much unwanted complexities to your code, and contains so much of external control, which ultimately requires you to keep an eye on this type of code every time you execute it.

List<String> list = Arrays.asList("Hi,", " I", " am", " Learning", " Lambda", "Expressions!!");
for (int i = 0; i < list.size(); i++) {
 System.out.print(list.get(i));
}

Another external iteration we have is Iterate for every ELEMENT of the collection i.e. below in the code if you see, it does the same thing as above but decreases some external control. But the complexity level is same.

List<String> list = Arrays.asList("Hi,", " I", " am", " Learning", " Lambda", "Expressions!!");
for (String e : list) {
 System.out.print(e);
}

As an option in Java for collections, fortunately we have an internal iterator i.e. in below code you will see how forEach iterates over the collection without any external control required.

List<String> list = Arrays.asList("Hi,", " I", " am", " Learning", " Lambda", "Expressions!!");
list.forEach(new Consumer<String>() { 
    @Override public void accept(String t) {
       System.out.print(t);
    }
 });

But it again contains an Anonymous class (the unwanted noise ) to be dealt with, and we already know how to get rid of anonymous classes smoothly. Well, in the below code you can see how the above all types of iteration methods can be avoid with their great complexities and the Lambda can be adopted in any type of requirement( where ever an anonymous class is needed).

List<String> list = Arrays.asList("Hi,", " I", " am", " Learning", " Lambda", "Expressions!!");
System.out.println("\n\nInternal iteration:");
//list.forEach((t) -> System.out.print(t));
list.forEach(System.out::print); // converted lambda to simple method referrencing.

Note : Above invakation is only applicable if a single passed is value to method inside.

No worries of external control, data types and all unrequired garbage. Thats how Lambdas are awesome. That’s how Java becomes more intelligent using Lambda Expressions.

5. Why Lambdas?

As we have gone through all the uses and code level use of Lambda, we have under standing why should we use it. But I would like to explain a bit more as a wrap up, some bullet points are mentioned below which exactly reasons about why should we adopt Lambdas asap.

  1. Enables Functional Programming.

                All new JVM based languages are taking advantage of functional paradigm in their Applications, but programmers are forced to work with Object Oriented Programming till lambda came. So, now Lambdas enables us to write functional code.

  1. Readable and Concise Code.

                People have started using Lambdas and reported that Lambda helped them to remove a huge number of lines from their code. The boiler plate code can easily be removed using Lambdas, ofcourse in a certains situations.

  1. Easy-to-Use APIs and Libraries.

               The APIs designed using Lambda are easier to use and support other APIs.

  1. Enables Support for Parallel Processing.

               Lambdas also enables to write Parallel processing. Because, every processor is a multi-core processor nowadays, so, having support for parallel processing and ability to write code that can be execute on Parallel Processors is a Big Deal. That can easily implemented using Lambdas.

Hopefully this may help you in exploring your Java 8 concepts.

References taken from youtube videos of Venkat Subramaniam about Lambdas in Java 8.

Written by 

Yashpal, is a software consultant at Knoldus Inc, having more than 2.5 years of working experience. Yash is familiar with programming languages such as Java and Scala and he is currently working on reactive technologies like Scala, Lagom, Akka, Spark, and Kafka. Yash is also a proactive learner of new technologies and languages. His hobbies include playing chess, Table Tennis and basketball, watching Hollywood movies & series and he also loves listening to good music and singing Indian Vocal.

1 thought on “Lambda Expression9 min read

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading