Falando sobre programação funcional

  1. Conheça a interface funcional

Primeiro, apresente a interface funcional. Uma interface funcional é uma interface que tem apenas um método abstrato (pode haver vários métodos não abstratos). Interfaces funcionais comuns incluem Runnable, Comparable, etc.

@FunctionalInterface
public interface Runnable {
    
    
    void run();
}

public interface Comparable<T> {
    
    
    int compareTo(T var1);
}

Após jdk1.8, interfaces funcionais comuns (Função, Consumidor, Predicado, Fornecedor, BiFunction, IntBinaryOperator) e suas interfaces funcionais derivadas no pacote java.util.function foram adicionadas.

public interface Consumer<T> {
    
    
    void accept(T var1);
}

public interface Function<T, R> {
    
    
    R apply(T var1);
}

public interface Predicate<T> {
    
    
    boolean test(T var1);
}

public interface Supplier<T> {
    
    
    T get();
}

public interface BiFunction<T, U, R> {
    
    
    R apply(T var1, U var2);
}

public interface IntBinaryOperator {
    
    
    int applyAsInt(int var1, int var2);
}

Todas as interfaces funcionais acima usam genéricos, a diferença está na assinatura do método. Portanto, este artigo usa apenas as duas primeiras interfaces funcionais como exemplos. Os outros princípios são semelhantes. Primeiro, use a Função como exemplo:

public class FunctionClient {
    
    
    String clientPrint() {
    
    
        return "this is functionClient test";
    }

    public static void main(String[] args) {
    
    
        FunctionInterface functionInterface = new FunctionInterface();
        //第一种写法
        System.out.println(functionInterface.functionTest(FunctionClient::clientPrint));
        //第二种写法
        System.out.println((String) functionInterface.functionTest(functionClient -> functionClient.clientPrint()));
    }
}

class FunctionInterface {
    
    
    FunctionClient functionClient = new FunctionClient();
    <R> R functionTest(Function<FunctionClient, R> function) {
    
    
        return function.apply(functionClient);
    }
}

A interface funcional usada aqui é Function, que corresponde ao método apply. O FunctionTest na classe FunctionalInterface é usado para simular a interface que os desenvolvedores de SDK fornecem aos desenvolvedores de software. O parâmetro de entrada desta interface é Function e o parâmetro de saída é R :

<R> R functionTest(Function<FunctionClient, R> function) {
    
    
    return function.apply(functionClient);
}

Quando o objeto de função chama o método apply, ele realmente executa o código atrás da seta, que é functionClient.clientPrint (). O parâmetro de entrada de functionTest é a expressão "functionClient -> functionClient.clientPrint ())". O tipo executado no lado direito da seta é o tipo de valor de retorno da interface funcional. Como functionClient.clientPrint () retorna String, então aqui está R Também se refere especificamente ao tipo String.

Além do objeto FunctionClient especificado acima, é possível usar tipos comuns em vez da classe FunctionClient no lado esquerdo da seta?

public class FunctionClient {
    
    
    String clientPrint() {
    
    
        return "this is functionClient test";
    }

    public static void main(String[] args) {
    
    
        FunctionInterface functionInterface = new FunctionInterface();
        Function<String, String> function = "This is left param." -> new FunctionClient().clientPrint();//报错行
        System.out.println(functionInterface.functionTest(function));
    }
}

class FunctionInterface {
    
    
    <R> R functionTest(Function<String, R> function) {
    
    
        return function.apply("This is FunctionalInterface");
    }
}

O código acima não será compilado porque Function não pode aceitar o tipo String e outras constantes. Como o lado esquerdo da seta representa o parâmetro de entrada de um método, o parâmetro de entrada só pode ser uma variável para o método, portanto, um erro será relatado se for definido diretamente como uma constante.

Então, como representar uma cena sem parâmetros? Basta definir uma variável não declarada no lado esquerdo da seta:

Function<String, String> function = s -> new FunctionClient().clientPrint();

Para a atribuição de uma interface funcional, o lado esquerdo da seta só precisa passar o número correspondente de nomes de variáveis ​​não atribuídas.Se não houver parâmetro de entrada, basta usar ().

Se houver apenas um valor de retorno e nenhum parâmetro, você pode usar a interface do Fornecedor:

public class FunctionClient {
    
    
    String clientPrint() {
    
    
        return "this is functionClient test";
    }

    public static void main(String[] args) {
    
    
        FunctionInterface functionInterface = new FunctionInterface();
        Supplier<String> function = () -> new FunctionClient().clientPrint();
        System.out.println(functionInterface.functionTest(function));
    }
}

class FunctionInterface {
    
    
    <R> R functionTest(Supplier<R> function) {
    
    
        return function.get();
    }
}
  1. Quais são as vantagens da programação funcional?

Simplifique o código, como:

Runnable runnable1 = new Runnable() {
    
    
    @Override
    public void run() {
    
    
        System.out.println("Runnable");
    }
};

//第一次简化,函数式编程(语句lambda形式)
Runnable runnable2 = () -> {
    
    
    System.out.println("Runnable");
};

//第二次简化,函数式编程(表达式lambda形式)
Runnable runnable3 = () -> System.out.println("Runnable");

又比如:

Consumer<Integer> consumer = i -> System.out.println(i);
List<Integer> arrayList = new ArrayList<>(){
    
    
    {
    
    
        add(1);
        add(2);
        add(4);
    }
};
arrayList.forEach(consumer);
  1. A relação entre lambda, programação funcional e callbacks

1. Lambda é uma implementação de uma interface funcional, que pode ser entendida como açúcar sintático.
2. O retorno de chamada não tem limite no número de métodos na interface, mas as interfaces funcionais podem especificar apenas um método abstrato.
3. As definições de método de programação funcional e retorno de chamada estão no chamador e as entradas de ambos são interfaces, mas uma delas é uma interface normal e a outra é uma interface funcional.
4. Os métodos de programação funcional e callback são executados no receptor, o primeiro executa o único método correspondente, como o apply, enquanto o segundo pode corresponder a vários métodos, basta executar o método correspondente.
5. Ambos podem usar lambda para definir a implementação do método no chamador.
6. A implementação da programação funcional é um retorno de chamada especial.

Acho que você gosta

Origin blog.csdn.net/weixin_48968045/article/details/113148594
Recomendado
Clasificación