I tried to summarize Java lambda expressions

What is a lambda expression?

A new grammar introduced in Java 8. Simplify the processing description by omitting the contents to be described using the local class and the anonymous class. As typical examples, the methods of Collections.sort and Stream API have benefited.

Decomposition of lambda expression

Lambda expressions use a mechanism called local classes and anonymous classes.

  1. Local class

A local class is a mechanism that can be used by declaring a class during method processing.

public static void main(String[] args) {

  class Local {
    public void sayHello() {
      System.out.println("Hello!");
    }
  }

  Local local = new Local();
  local.sayHello(); // Hello!
}

You can also define a local class that implements the interface.

public static void main(String[] args) {

  class Local implements Runnable {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  }

  Runnable runner = new Local();
  runner.run(); // Hello Lambda!
}

Next, let's take a look at the anonymous class.

  1. Anonymous class

Anonymous class is a mechanism that omits the declaration of the local class that implements the interface. Here is an example of an anonymous class that implements the Runnable interface.

public static void main(String[] args) {

  Runnable runner = new Runnable() {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  };

  runner.run(); //Hello Lambda!
}

It looks as if you are instantiating the Rannable interface, but you are actually creating an instance of an anonymous class that implements the Rannable interface. Finally, let's take a look at the lambda expression.

  1. Lambda expression

It becomes a lambda expression by omitting "new Runnable () {}" and "public void run" from the anonymous class.

public static void main(String[] args) {

  Runnable runner = () -> { System.out.println("Hello Lambda!"); };
  runner.run(); //Hello Lambda!
}

The first () represents the argument of the run method, and the contents of-> {} are the implementation contents of the run method. An instance of an anonymous class that implements Runnable is assigned to the runner variable. In other words, a lambda expression is an expression that creates an instance that implements the interface.

By the way, if you omit "new Runnable () {}", you don't know what type of instance to create. In Java, it is a mechanism to infer automatically according to the type of the variable to be assigned. This mechanism is called type inference.

Also, if you omit "public void run", you won't know which method to override for an interface that has multiple methods defined. Therefore, a lambda expression can only use an interface with one abstract method.

Only the Rannable interface can create lambda expressions with no arguments and no return value. If you want to create it in another form, a functional interface has been added, so use that.

Functional interface

A functional interface is an interface that can be assigned to a lambda expression or method reference.

The condition of a functional interface is, roughly speaking, an interface that has only one abstract method defined. Static methods and default methods can be included (ignored as a condition of functional interfaces). Also, if a public method in the Object class is defined as an abstract method in the interface, that method is also ignored. (Interfaces that meet this condition are now called "functional interfaces" in JDK 1.8)

A lot of interfaces have been added under the java.util.function package from SE8. https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/package-summary.html

This time, I will introduce the interface that I often use.

2-1. Function<T, R> Function is a functional interface for converting values. In Function \ <T, R>, T specifies the method argument type, and R specifies the return type. Takes an argument, converts (calculates) it, and returns another value. The method is R apply (T).

Function<Integer, String> asterisker = (i) -> { return "*"+ i; };
String result = asterisker.apply(10);
System.out.println(result); // *10

2-2. Consumer<T> Consumer is a functional interface for receiving arguments and using them for processing. T in Consumer \ specifies the type of method argument. Since it does not return a value, it is basically used for the purpose of causing side effects. The method is void accept (T).

Consumer<String> buyer = (goods) -> { System.out.println(goods + "I bought"); };
buyer.accept("rice ball"); // rice ballを購入しました。

2-3. Predicate<T> Predicate is a functional interface for making judgments. T in Predicate \ specifies the type of method argument. It receives an argument, makes a judgment, and returns a boolean value (judgment result). The method is boolean test (T).

Predicate<String> checker = (s)-> { return s.equals("Java"); };
boolean result = checker.test("Java");
System.out.println(result); //true

Intention to use lambda expression

The following code describes the Stream API using a lambda expression.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);
numbers.stream()
        .filter(number -> Math.abs(number) >= 5)
        .forEach(System.out::println);

The output result is as follows.

-5
9
6
5
5

Next, let's take a look at the code written without using a lambda expression.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);

numbers.stream()
        .filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer number) {
                return Math.abs(number) >= 5;
            }
        })
        .forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer number) {
                System.out.println(number);
            }
        });

As introduced in the decomposition of lambda expression, the method description to generate and execute the interface is increasing, so The amount of code written has increased and the processing outlook has become very poor. In this way, it is used to make the processing description concise and easy to understand.

Lambda grammar

Explains the grammar of lambda expressions. Below is the basic grammar of a lambda expression.

(argument) -> {processing; }

The following is written according to this grammar.

// (1)If there are arguments and a return value
(Integer number) -> {
    return Math.abs(number) >= 5;
}

// (2)If there is no return value
(Integer number) -> {
    System.out.println(number);
}

// (3)If there are no arguments or return values
() -> {
    System.out.println("Hello!");
}

(1) is an example that has an argument and a return value like Predicate. Processing is performed using the number specified by the argument, and the return value is returned. (2) is an example where there is no return value like Consumer. In that case, there is no need to write a return statement. For processing without arguments as in (3), describe the argument part in (). For example, java.lang.Runnable.

You can also omit the argument type in a lambda expression. And you can omit the parentheses () around the argument only if you have only one argument. It cannot be omitted if there is no argument or if there are two or more. Applying this rule to (1) and (3) gives:

// (1)Because it has one argument( )Can be omitted
number -> {
    return Math.abs(number) >= 5;
}

// (3)Because there are no arguments( )Cannot be omitted
() -> {
    System.out.println("Hello!");
}

In addition, if there is only one line, you can omit the curly braces {}, return, and the semicolon at the end of the sentence. The abbreviations for (1) to (3) are as follows.

// (1)If there are arguments and a return value
number -> Math.abs(number) >= 5

// (2)If there is no return value
number -> System.out.println(number)

// (3)If there are no arguments or return values
() -> System.out.println("Hello!")

Finally, the argument itself can be omitted by using the method reference only when the processing content is one method call and the argument is uniquely determined. The method reference has the following syntax.

name of the class::Method name

This method reference can only be applied in (2). If (2) is described using the method reference, it will be as follows.

System.out::println

The System.out.println method is a method that takes only one argument, and it is clear that the value of the argument Integer is passed, so a method reference is available. On the other hand, in (1), the method reference cannot be used because there is a magnitude judgment of> = 5 after the method call. Also, in (3), since the value "Hello!" Is specified for the argument, it cannot be said that the argument is uniquely determined, and the method reference cannot be used for this either.

With this in mind, let's take a look at the stream processing earlier.

List<Integer> numbers = List.of(3, 1, -4, 1, -5, 9, -2, 6, 5, 3, 5);
numbers.stream()
        .filter(number -> Math.abs(number) >= 5)
        .forEach(System.out::println);

You can see that the lambda expression learned in (1) and (2) is embedded in the streamAPI.

Reference article

Understanding Java 8 Lambda Expressions Modern Java Learned with Lambda Expressions and Stream APIs-The Present of the Java Language Changing with Functionals

Recommended Posts

I tried to summarize Java lambda expressions
I tried to summarize Java learning (1)
I tried to summarize Java 8 now
[Java] Introduction to lambda expressions
[Introduction to Java] About lambda expressions
I tried to summarize iOS 14 support
I tried to interact with Java
How to use Java lambda expressions
I tried to summarize the basics of kotlin and java
I tried to summarize the methods used
I tried to summarize the Stream API
What is Docker? I tried to summarize
I tried to summarize the methods of Java String and StringBuilder
Understand Java 8 lambda expressions
About Java lambda expressions
Explain Java 8 lambda expressions
I tried to summarize about JVM / garbage collection
I tried to make Basic authentication with Java
[Java] Summary of how to abbreviate lambda expressions
java I tried to break a simple block
I tried to implement deep learning in Java
[Must see !!!] I tried to summarize object orientation!
I tried to output multiplication table in Java
I tried to create Alexa skill in Java
I tried to break a block with java (1)
[Introduction to Java] I tried to summarize the knowledge that I think is essential
I tried to implement TCP / IP + BIO with JAVA
I tried to implement Firebase push notification in Java
[Java 11] I tried to execute Java without compiling with javac
I tried to summarize the state transition of docker
[Java Silver] Summary of points related to lambda expressions
[Java] I tried to solve Paiza's B rank problem
I tried to operate SQS using AWS Java SDK
# 2 [Note] I tried to calculate multiplication tables in Java.
I tried Java Lambda input / output type ~ Stream version ~
I tried to create a Clova skill in Java
I tried Drools (Java, InputStream)
I tried to make a login function in Java
I tried to summarize various link_to used this time
I tried to implement Stalin sort with Java Collector
I tried using Java REPL
[Java] I tried to implement Yahoo API product search
I tried to verify yum-cron
I tried to implement the Euclidean algorithm in Java
~ I tried to learn functional programming in Java now ~
I tried metaprogramming in Java
I tried to find out what changed in Java 9
I tried to create a java8 development environment with Chocolatey
I tried to modernize a Java EE application with OpenShift.
[JDBC] I tried to access the SQLite3 database from Java.
I tried to make Java Optional and guard clause coexist
I tried to summarize the basic grammar of Ruby briefly
I tried to summarize personally useful apps and development tools (development tools)
I tried to convert a string to a LocalDate type in Java
I tried to summarize personally useful apps and development tools (Apps)
I tried using Dapr in Java to facilitate microservice development
I tried to make a client of RESAS-API in Java
I tried to summarize object orientation in my own way.
Java lambda expressions learned with Comparator
I tried to chew C # (indexer)
I tried UDP communication with Java