Explanation of lambda expressions

Original author: Per-Erik Bergman
  • Transfer

Explanation of lambda expressions


I have questions about lambda expressions and RxJava. These questions mostly concern an incomplete understanding of lambda expressions or RxJava. I will try to explain lambda expressions as simple as possible. RxJava I will describe separately.


Lambda Expressions and RxJava


What are lambda expressions? Lambda expressions are “just” a new way to do the same thing that we could always do, but in a cleaner and less verbose new way of using anonymous inner classes.


An anonymous inner class in Java is an unnamed class, it should be used if you need to override class or interface methods. An anonymous inner class can be created from a class or interface.


For instance:


abstract class Animal {
   abstract void speak();
}
Animal a = new Animal() {
   void speak() {
       System.out.println("Woff");
   }
};

On Android, we usually use an anonymous inner class as a listener, for example, for buttons of this kind:


Button btn = findViewById(R.id.button);
btn.setOnClickListener(
       new View.OnClickListener() {
           @Override
           public void onClick(final View view) {
               // Do some fancy stuff with the view parameter.
           }
       }
);

Let's get back to lambda expressions. This is the next part, which is part of the previous code, which is considered an anonymous inner class.


new View.OnClickListener() {
   @Override
   public void onClick(final View view) {
       // Do some fancy stuff with the view parameter.
   }
}

Lambda expressions can only be used if you need to override at most one method. Fortunately for us, View.OnClickListener contains only one. Take a look at the code below. What part do you think we have to remove?


new View.OnClickListener() {
   @Override
   public void onClick(final View view) {
       // Do some fancy stuff with the view parameter.
   }
}

After removing almost all the code, we need to add ->, as in the code below. The input parameter view can be used inside the function in the same way as before.


(view) -> {
   // Do some fancy stuff with the view parameter.
}

In some cases, you may need to add a type to a parameter, if the compiler cannot guess it, you can do this by adding it before the parameter:


(View view) -> {
   // Do some fancy stuff with the view parameter.
}

You can also use multi-line code:


(view) -> {
   Intent intent = new Intent(context, AuthActivity.class);
   intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |     Intent.FLAG_ACTIVITY_CLEAR_TASK);
   view.getContext().startActivity(intent);
} 

If you have an interface with a method that takes two parameters ...


interface MyInterface {
   abstract void onMethod(int a, int b);
} 

... the lambda expression will look like this:


(a, b) -> {
   // Do some fancy stuff with the a and b parameter.
}

If the method has a return type ...


interface MySecondInterface {
   abstract int onSecondMethod(int a, int b);
}

... the lambda expression will look like this:


(a, b) -> {
   return a + b;
}

But that’s not all, there are some special cases that make the code even smaller. If your method body contains only one line of code, you can remove the curly braces {} . If you remove curly braces, you also need to remove the semicolon, leaving the following:


(a, b) -> return a + b

There is one more thing we can do. If we have only one line of code, then the compiler can understand whether the returned part is needed or not, so we can leave it like this:


(a, b) -> a + b

If we had multi-line code, it would come down to the following:


(a, b) -> {
   a+=1;
   return a + b;
}

So what have we done? We took this:


new MySecondInterface() {
   @Override
   public int onSecondMethod(final int a, final int b) {
       return a + b;
   }
};

and turned it into this:


(a, b) -> a + b

There is only one thing left, method references. Suppose we have an interface, as before, and a method that accepts this interface as a parameter:


public interface Callback {
   public void onEvent(int event);
}
public void myMethod(Callback callback){
}

Without a lambda expression, it would look like this:


myMethod(new Callback() {
   @Override
   public void onEvent(final int state) {
       System.out.println(state);
   }
}); 

Adding a lambda expression, as we did before, we get the following:


myMethod(state -> System.out.println(state));

But that is not all. If the code used is single-line and the called function takes one parameter, we can pass the method reference in this form:


myMethod(System.out::println);

The parameter will be passed automatically, without the need for another code! Amazing right? I hope you learned something new!


Also popular now: