Java 8: как работает BiFunction при использовании методов andThen () и apply () - PullRequest
1 голос
/ 03 июня 2019

В настоящее время BiFunction интерфейс имеет два метода andThen() и apply().Я нашел разные примеры в сети, но нижеприведенный пример - это то, что я не могу понять - «Как работает цепочка этих методов»

Пример 1:

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"));

Прочитав следующую ссылку ' Метод Default andThen () в интерфейсе BiFunction ', я взял строки ниже

Предположим, у нас было две функции f и g, функция f выполняла некоторыелогика и функция g выполняют некоторый другой тип логики, поэтому, когда вы составляете f.andThen (g), это по существу означает g (f (x)), т.е. мы сначала применяем функцию, заданную в качестве аргумента f (x), а затем применяем функцию g крезультат.

и пришел к выводу, что сначала происходит bi.apply("hello", " world")), а затем result передается bi.andThen(f(result)), и это дает окончательный результат hello world spinner.

Я понялв некоторой степени, но не полностью удовлетворены.Я должен был спросить об этом, потому что в прошлом я использовал шаблон построителя, и это что-то вроде ниже,

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

Здесь, вызов метода происходит в последовательности, сначала класс Builder (статический) получаетинициализируется, затем withOwner назначает имя владельца и возвращает компоновщик, а затем присваивается имя ветви и возвращает компоновщик, дается следующий начальный баланс и возвращается компоновщик, и, наконец, сборка возвращает экземпляр BankAccount.Пожалуйста, смотрите BankAccount класс.

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;
        }
    }

}

Как видите, методы вызываются последовательно и вывод методов - withOwner, atBranch, openingBalance, является экземпляром Builderв цепочке.и для меня это называется цепочкой методов, потому что выходные данные каждого метода в последовательности используются позже, и это очень ясно.Но я спрашиваю - как работает цепочка методов из приведенного выше примера 1 (BiFunction and its methods chaining) внутренне .

Ответы [ 3 ]

0 голосов
/ 03 июня 2019

Это просто композиция функции , что означает, что если мы дадим получившейся функции имя:

BiFunction<String, String, String> composed = bi.andThen(f);

Тогда простое определение будет:

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

Итак, BiFunction.andThen возвращает BiFunction, который будет применять логику текущей (bi) функции для вычисления результата, который затем передается другой функции (f), применяя ее логику для возврата окончательного результата.

0 голосов
/ 03 июня 2019

Метод andThen отличается от шаблона Builder несколькими способами:

andThen возвращает новую функцию, которая является композицией двух других функций, тогда как каждый метод компоновщика возвращает себя, просто чтобы разрешить цепочку вызовов методов, что делает код более компактным, но вы также можете написать:

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

Кроме того, с помощью метода andThen все является неизменным, в то время как построитель является изменчивым по своей природе (хотя сам построенный объект часто является неизменным).

0 голосов
/ 03 июня 2019

Вы можете посмотреть на реализацию по умолчанию:

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));
}

Как видите, сначала они вызывают apply метод BiFunction (т.е. они оценивают apply(t, u)), а результат этого метода передается методу Function * apply ( after.apply(...)).

Я не уверен, почему вы чувствуете, что andThen не вызывает методы в последовательности. В конце концов bi.andThen(f) создает BiFunction, который сначала вызывает метод bi apply, а затем вызывает метод f apply (как следует из названия andThen).

...