Java and first-class functions-beyond functional interfaces-

Overview

Java 8 has enhanced functionality around functional programming.

--Functional interface --Method reference --Lambda expression --Stream API

Summarize what functional interfaces and method references do

Goal You will be able to read and use this source code.

public static void main(String[] args) {
    List<String> strings = Arrays.asList("bravo", "", "charlie", "alpha");
    strings.stream()
            .filter(s -> !s.isEmpty())
            .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1))
            .forEach(System.out::println);
             //  Bravo
             //  Charlie
             //  Alpha
}

Functional interface

What is a functional interface and what is it for? To understand it, it is necessary to understand the concept of ** first-class function **.

First-class function

First-class function (first-class function) [1] is the nature of a programming language that can treat a function as a first-class object, or such a function. That is. -[First-class function-Wikipedia](https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E9%96%A2%E6% 95% B0)

First-class citizen?

First-class citizen

First-class citizens (first-class objects) are an unlimited number of basic operations in a programming language, such as creation, assignment, arithmetic, and passing (as arguments / return values). It is an object that can be used. -[First Class Citizen--Wikipedia](https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88)

I see

What about Java?

Java functions (methods) cannot be assigned to variables or used for return values / arguments. Java is a language that does not meet the properties of first-class functions.

What makes you happy with first-class functions?

First-class functions are essential for functional languages and are routinely used in the form of higher-order functions. -[First-class function-Wikipedia](https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E9%96%A2%E6% 95% B0)

** Behavior can be manipulated by functions from the outside. ** ** e.g. sort rules

List<String> strings = Arrays.asList("bravo", "charlie", "alpha");

Collections.sort(strings);
System.out.println(strings); // -> [alpha, bravo, charlie]

Collections.sort(strings, Comparator.reverseOrder());
System.out.println(strings); // -> [charlie, bravo, alpha]

Benri.

wait a minute

Isn't it the current code Java?

Strategy pattern

A design pattern conceived because a function is not available as a first-class citizen.

In Java, the Strategy pattern can be implemented using polymorphism with method overrides in classes. --Strategy pattern --Wikipedia

I will omit the details, but it looks like this.

public static <T> void sort(List<T> list, Comparator<? super T> c) {
    if (c.compare(a, b) < 0) {
        //a is smaller
    }else {
        //b is smaller
    }
}

The sorting rule is determined according to the implementation class of the Comparator interface received as an argument. The practice that the method itself is not passed via an argument, but the method processing can be passed from the outside through the interface.

The actual sort process looks like this jdk/TimSort.java at master · openjdk/jdk

This design pattern does not need to be particularly noticeable in languages where functions are first-class citizens.

This pattern is implicitly used in languages where the function is a first-class citizen. --Strategy pattern --Wikipedia

Real

Java can handle functions (methods) like first-class citizens by using interfaces.

What is a functional interface?

From java8, the interface used to treat a function (method) as a first-class object, like the Comparator mentioned earlier, is called a ** functional interface **. Since the purpose is to treat functions (methods) as first-class citizens, there is only one abstract method for functional interfaces.

Some of the interfaces that have been provided in the past, such as Comparator and Runnable, have just been given new names. The function is the same as a normal interface. Annotation ** @ FunctionalInterface ** is now added to functional interfaces. e.g. java.lang.Runnable

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

jdk/FunctionalInterface.java at master · openjdk/jdk

@FunctionalInterface Annotations added for functional interfaces. Nothing happens at runtime (functional interfaces are functionally normal interfaces, so there is no special processing). At compile time, it checks if it meets the properties of a functional interface.

In other words, it is not absolutely necessary when using the functions of the functional interface. However, since it can be clearly stated that it is a functional interface rather than a normal interface, it seems that it should be added when creating a functional interface by yourself.

Standard functional interface

When handling a function (method) using a functional interface, the method to be handled is affected by the Java type system. Specifically, when dealing with different methods below, different functional interfaces must be used.

--Return type --Argument type --Number of arguments

java8 provides a standard functional interface that abstracts and makes available the presence / absence of return values and the types of arguments. Basically, this interface is sufficient, and it is said that you should consider using this interface. (Except for customary ones such as Runnable)

** Typical standard functional interface **

Interface name Abstract method name Example
Function<T,R> R apply(T t) Arrays::asList
Predicate boolean test(T t) Collections::isEmpty
Consumer<T> void accept(T t) System.out::println
Supplier<T> T get() Instant::now
UnaryOperator<T> T apply(T t) String::toLowerCase
BinaryOperator<T> T apply(T t1, T t2) BigInteger::add

java.util.function (Java Platform SE 8 )

Actually use

Let's create a process to process and output a character string. When calling the output process, the character string after the processing process is output by passing the processing process function together. Try to build a program that outputs after converting all to uppercase.

Character string display part

Output after executing the passed function. The functional interface assumes a function that receives one string before change (String) and returns the string after change (String), and uses ʻUnaryOperator `.

static void print(String word, UnaryOperator<String> operator) {
    String newWord = operator.apply(word);
    System.out.println(newWord);
}

Function to pass

A function that converts to uppercase. ʻImplement UnaryOperator `.

import java.util.function.UnaryOperator;

public class MyUpperOperator implements UnaryOperator<String> {
    @Override
    public String apply(String s) {
        return s.toUpperCase();
    }
}

main If you pass the capitalization function created earlier and the character string to the print method, all capital letters will be output.

public static void main(String[] args) {
    UnaryOperator<String> upperOperator = new MyUpperOperator();
    print("hello world", upperOperator); // -> HELLO WORLD
}

Well

It uses a functional interface, but it's just a Strategy pattern.

Method reference

In the previous example, in fact, a more powerful writing style is possible. By using a function called ** method reference **, it is possible to directly pass a method whose arguments and return values match without explicitly implementing a functional interface. In the case of the previous example, since ʻUnaryOperator , if the method consists of one String and the return value is String, it can be passed directly as a method reference. You can assign the toUpperCase ()method of theString class directly to the ʻUnaryOperator <String> instance. (In the case of a method reference of an instance method, the receiver object is interpreted as the first argument. See the syntax below.) When this happens, the calling source code appears to treat the function as a first-class citizen.

public static void main(String[] args) {
    // UnaryOperator<String> upperOperator = new MyUpperOperator();
    UnaryOperator<String> upperOperator = String::toUpperCase;
    print("hello world", upperOperator); // -> HELLO WORLD
}

How it works is difficult

It seems that it uses the instruction ʻinvoke Dynamic` of the JVM. It seems that the class is dynamically generated and solved at runtime, not at compile time.

grammar

Notation of two consecutive semicolons. The content described on both sides of the semicolon can be roughly divided into four patterns depending on the type of method.

Target grammar Example
Class method name of the class::Class method name String::toString
Instance method Instance name::Instance method name System.out::println
Instance method * name of the class::Instance method name String::toUpperCase
constructor name of the class::new String::new

Try using

The previous example can be described very briefly. The MyUpperOperator class is no longer needed.

public static void main(String[] args) {
    print("hello world", String::toUpperCase); // -> HELLO WORLD
}

Also, many of the stream APIs added in java8 require a functional interface, so this kind of processing can be done.

public static void main(String[] args) {
    List<String> strings = Arrays.asList("bravo", "charlie", "alpha");
    strings.stream()
            .map(String::toUpperCase)// Function:Convert to uppercase
            .forEach(System.out::println);// Consumer:output
            // BRAVO
            // CHARLIE
            // ALPHA
}

Very convenient, but

It is necessary to declare the method in advance in order to handle it. It's good to use the provided methods, but you have to declare your own processing as a method one by one. I want to treat methods like literals.

Lambda expression

An evaluation expression mechanism that can be assigned to a functional interface. You can write a method as an expression without declaring the method.

e.g. Function to add a period to a string

public static void main(String[] args) {
//    UnaryOperator<String> upperOperator = String::toUpperCase;
    UnaryOperator<String> periodOperator = (String s) -> { return s + "."; };
    print("hello world", periodOperator); // -> hello world.
}

grammar

This is the basic form (Formal argument string)-> {Processing body statement} e.g. (String s) -> { return s + "."; }

Various descriptions can be omitted only under specific conditions. I will omit it because I think that various things will come out if I look it up. e.g. In this case UnaryOperator<String> periodOperator = s -> s + ".";

Try using

public static void main(String[] args) {
    print("hello world", s -> s + "."); // -> hello world.
}

public static void main(String[] args) {
    List<String> strings = Arrays.asList("bravo", "", "charlie", "alpha");
    strings.stream()
            .filter(s -> !s.isEmpty()) // Predicate:Remove empty string
            .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1)) // Function:Convert only the first character to uppercase
            .forEach(System.out::println); // Consumer:output
             //  Bravo
             //  Charlie
             //  Alpha
}

An example of the latter is the process mentioned at the beginning of this article.

You will be able to read and use this source code.

Summary

Functional programming has been enhanced since java8.

--Functional interface --Method reference --Lambda expression

reference

Revised 2nd Edition Perfect Java: Book Guide | Gijutsu-Hyoronsha Effective Java 3rd Edition-Maruzen Publishing Co., Ltd., a specialized book publisher of science, engineering, medicine, and humanities and social sciences

Recommended Posts

Java and first-class functions-beyond functional interfaces-
Java and JavaScript
XXE and Java
[Java] Functional interface
Effective Java 3rd Edition Chapter 4 Classes and Interfaces
Getters and setters (Java)
[Java] Thread and Runnable
java standard functional interface
Java true and false
[Java] String comparison and && and ||
Java --Serialization and Deserialization
[Java] Arguments and parameters
timedatectl and Java TimeZone
[Java] Branch and repeat
[Java] Variables and types
java (classes and instances)
[Java] Overload and override
Study Java # 2 (\ mark and operator)
Java version 8 and later features
[Java] Functional interface / lambda expression
[Java] Difference between == and equals
[Java] Stack area and static area
[Java] Generics classes and generics methods
Try functional type in Java! ①
Java programming (variables and data)
Java encryption and decryption PDF
Java and Iterator Part 1 External Iterator
Java if and switch statements
Java class definition and instantiation
Apache Hadoop and Java 9 (Part 1)
[Java] About String and StringBuilder
[Java] HashCode and equals overrides
☾ Java / Iterative statement and iterative control statement
Java methods and method overloads
java Generics T and? Difference
Advantages and disadvantages of Java
java (conditional branching and repetition)
Implement functional quicksort in Java
About Java Packages and imports
[Java] Upload images and base64
C # and Java Overrides Story
Java abstract methods and classes
Java while and for statements
Java encapsulation and getters and setters