3
votes

Java 8: comment fonctionne BiFunction lors de l'utilisation des méthodes andThen () et apply ()

Actuellement, l'interface BiFunction a deux méthodes andThen () et apply () . J'ai trouvé différents exemples sur le Web, mais l'exemple ci-dessous est quelque chose que je n'arrive pas à comprendre - "Comment fonctionne le chaînage de ces méthodes"

Exemple 1:

public class BankAccount {

    public static class Builder {

        private long accountNumber; 
        private String owner;
        private String branch;
        private double balance;

        public Builder(long accountNumber) {
            this.accountNumber = accountNumber;
        }

        public Builder withOwner(String owner){
            this.owner = owner;
            return this; 
        }

        public Builder atBranch(String branch){
            this.branch = branch;
            return this;
        }

        public Builder openingBalance(double balance){
            this.balance = balance;
            return this;
        }



        public BankAccount build(){
            //Here we create the actual bank account object, which is always in a fully initialised state when it's returned.

            BankAccount account = new BankAccount();  //Since the builder is in the BankAccount class, we can invoke its private constructor.
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            account.branch = this.branch;
            account.balance = this.balance;

            return account;
        }
    }

}

Après avoir lu le lien suivant ' Méthode par défaut andThen () dans l'interface BiFunction ', j'ai pris les lignes ci-dessous

Supposons que nous ayons deux fonctions f et g, la fonction f faisant de la logique et la fonction g faisant un autre type de logique, donc lorsque vous composez f.et Ensuite (g) cela signifie essentiellement g (f (x)) c'est-à-dire que nous appliquons d'abord la fonction donnée en argument f (x) puis appliquer la fonction g au résultat.

et a conclu que bi.apply ("bonjour", "monde")) se produit en premier, puis le résultat est transmis à bi.andThen (f (result)) et cela donne la sortie finale hello world spinner .

J'ai compris dans une certaine mesure, mais pas Totalement satisfait. J'ai dû poser cette question parce que dans le passé, j'ai utilisé un modèle de générateur et c'est quelque chose comme ci-dessous,

BankAccount account = new BankAccount.Builder("bank_account")
                                 .withOwner("account_owner")
                                 .atBranch("branch_name")
                                 .openingBalance(balance)
                                 .build();

Ici, l'appel de méthode se produit en séquence, d'abord le La classe Builder (statique) est initialisée, puis withOwner attribue le nom du propriétaire et renvoie le constructeur, puis le nom de la branche est attribué et renvoie le constructeur, le prochain solde d'ouverture est donné et renvoie le constructeur, et finalement la construction renverra l'instance BankAccount . Veuillez consulter la classe BankAccount .

BiFunction<String, String,String> bi = (x, y) -> {
                    return x + y;
                    };

Function<String,String> f = x-> x+" spinner";

System.out.println(bi.andThen(f).apply("hello", " world"));

Comme vous pouvez le voir, les méthodes sont appelées dans l'ordre et la sortie des méthodes - withOwner code>, atBranch , openingBalance , est une instance de Builder dans la chaîne. et pour moi, cela s'appelle le chaînage des méthodes, car la sortie de chaque méthode en séquence est utilisée pour plus tard et c'est très clair. Mais, ma question est - comment le chaînage des méthodes de l'exemple ci-dessus 1 (BiFunction et ses méthodes chaînage) fonctionne en interne


1 commentaires

Je doute que la documentation de andThen lit chaînage n'importe où. De plus, je ne vois pas l'intérêt de comparer un modèle Builder avec une fonction composée. Qu'est-ce qui crée la confusion ici?


3 Réponses :


1
votes

Vous pouvez regarder l'implémentation par défaut:

default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t, U u) -> after.apply(apply(t, u));
}

Comme vous pouvez le voir, ils appellent d'abord la méthode apply de la BiFunction (c'est-à-dire qu'ils évaluent apply (t, u) ), et le résultat de cette méthode est passé à la méthode apply de la Function ( after.apply (...) ).

Je ne sais pas pourquoi vous pensez que andThen n'appelle pas les méthodes dans l'ordre. Après tout, bi.andThen (f) crée une BiFunction qui appelle d'abord la méthode bi apply puis appelle La méthode apply de f (tout comme le nom andThen l'indique).


0 commentaires

0
votes

C'est une simple composition de fonction , c'est-à-dire si nous donnions un nom à la fonction résultante:

composed(x,y) = f(bi(x,y))

Alors une définition simple serait:

XXX

Donc BiFunction.andThen renvoie une BiFunction qui appliquera la logique de la fonction actuelle ( bi ) pour calculer un résultat qui est ensuite passé à une autre fonction ( f ), appliquant sa logique pour renvoyer la sortie finale.


0 commentaires

0
votes

La méthode andThen diffère du modèle Builder de plusieurs manières:

andThen renvoie une nouvelle fonction qui est la composition de deux d'autres fonctions, alors que chaque méthode du constructeur se retourne d'elle-même, juste pour permettre le chaînage des appels de méthode, rendant ainsi le code plus compact, mais vous pouvez aussi écrire:

BankAccount.Builder builder = new BankAccount.Builder("bank_account");
builder.withOwner("account_owner");
builder.atBranch("branch_name");
builder.openingBalance(balance);
BankAccount account = builder.build();

Aussi , avec la méthode andThen , tout est immuable, alors que le constructeur est intrinsèquement mutable (bien que l'objet construit soit souvent lui-même immuable).


0 commentaires