Как мы можем добавить (4) (10) (20) (3) (1) .total, используя функцию Java?

Я изучаю использование,

java.util.function.Function

Я написал код, который использует функцию java для добавления 4 к себе,

код выглядит следующим образом,

public class Test01 {

    public static void main(String[] args) {
        Function<Integer,Integer> addFunction = new Function<Integer,Integer>() {
            private int total = 0; 
            public Integer apply(Integer value) {               
                this.total += value; 
                return this.total;
            }
        };



        int finalTotal = addFunction.andThen(addFunction)
                                    .andThen(addFunction)
                                    .andThen(addFunction)
                                    .apply(4);

        System.out.println(finalTotal);
    }

}

Когда я запускаю приведенный выше код, я получаю вывод

32

Как я могу добиться того, что я сделал в javaScript, а именно:

var fn19 = function(){

        var addNum = function(num){

            var fn = function(num2){
                fn.sum += num2;             
                return fn;
            };

            fn.sum = num;   
            return fn;
        };

        print("addNum(3)(4)(3)(10) ==>  "+addNum(3)(4)(3)(10).sum); 
};

fn19();  

Вывод приведенного выше кода

addNum(3)(4)(3)(10) ==> 20

Могу ли я иметь такой же вызов функции Java, где я могу передать столько числовых аргументов, и addFunction добавит эти числа.

Не очень легко, так как Java — типизированный язык. Чтобы получить доступ к полю, вам нужно определить тип, который реализует Function<...>, но дает вам доступ к чему-то другому, кроме контракта этого интерфейса. Кроме того, вы, похоже, используете эквивалент Function<Integer,Function<Integer>> в своем коде Javascript, а не Functyon<Integer,Integer>.

RealSkeptic 07.04.2019 17:14

Как это связано с RxJava?

akarnokd 08.04.2019 09:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
115
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы не можете точно сделать это в Java, то, что вы ищете, это уменьшение поток значений.

Другими словами: «настоящее» функциональное решение здесь не в том, чтобы вызывать один метод с несколькими аргументами. У вас скорее есть значения в каком-то списке, а затем вы определяете функцию, которая «накапливается» по содержимому этого списка, применяя функцию к элементам.

См. здесь для некоторых примеров.

Техника, которую вы описываете в мире JavaScript, использует замыкание.

Это приятный побочный эффект того, что функции в JavaScript являются гражданами первого класса. Это способ связать функции с данными во внешней области видимости, а затем передать эту связь без потери внутреннего контекста. Наиболее распространенным/простым применением является кэширование (официальное название — мемоизация).

Вам понадобятся функции (методы) в Java, чтобы они были первоклассными, но это было бы избыточно, поскольку классы по дизайну представляют собой сущность, которая связывает данные и методы, что делает всю концепцию закрытия в этом контексте избыточной.

Ответ принят как подходящий

Примером, максимально приближенным к вашему коду JavaScript, будет

class QuestionableConstruct {
    int sum;
    QuestionableConstruct add(int num2) {
        sum += num2;
        return this;
    }
}
Runnable fn19 = () -> {
    IntFunction<QuestionableConstruct> addNum = num -> {
        QuestionableConstruct fn = new QuestionableConstruct();
        fn.sum = num;   
        return fn;
    };
    System.out.println("addNum(3)(4)(3)(10)==> "+addNum.apply(3).add(4).add(3).add(10).sum);
};
fn19.run();

Более похожее на Java решение было бы

interface Add {
    int sum();
    default Add add(int num) {
        int sum = sum() + num;
        return () -> sum;
    }
    static Add num(int num) {
        return () -> num;
    }
}

можно использовать как

System.out.println("addNum(3)(4)(3)(10) ==>  "+Add.num(3).add(4).add(3).add(10).sum());

В отличие от конструкции JavaScript, здесь используются настоящие неизменяемые функции. Рассмотреть возможность

Add a = Add.num(1).add(2).add(3);
System.out.println("1+2+3+4+5 = "+a.add(4).add(5).sum());
System.out.println("1+2+3+10+20 = "+a.add(10).add(20).sum());

который работает плавно без помех.

Но, конечно, если вы просто хотите суммировать переменное количество элементов, используйте

System.out.println("addNum(3)(4)(3)(10) ==>  "+IntStream.of(3, 4, 3, 10).sum()); 

или если вам нужен изменяемый аккумулятор, используйте

System.out.println("addNum(3)(4)(3)(10) ==>  "+
    IntStream.builder().add(3).add(4).add(3).add(10).build().sum());

что позволяет держать конструктор и передавать его.

Другие вопросы по теме