Написание лямбда-выражения для действительно базового c класса - PullRequest
2 голосов
/ 01 марта 2020

Существует два функциональных интерфейса

public interface BoolBiFunction {
boolean apply( int p1, int p2 );
}


public interface IntFunction {
int apply(int p);
}

И следующий класс

public class IntData {
private int[] intValues;

public IntData(int[] p) {
    intValues = p;
}

public int compute(BoolBiFunction f, IntFunction g, int x) {
    int result = 0;
    for (int value : intValues) {
        if (f.apply(value, x)) {
            result = result + g.apply(value);
        }
    }
    return result;
}

Задача состоит в использовании параметров, поэтому compute сообщает, как часто число встречается в поле intValues. Но, честно говоря, я не совсем понимаю, что делает данный метод вычисления.

if ( f.apply( value, x ) )
{
result = result + g.apply( value );
 }

f, кажется, сравнивает два целых числа, но что вообще делает g.apply? А как бы лямбда-выражение для проверки, как часто число встречается в поле intValues?

Ответы [ 3 ]

1 голос
/ 01 марта 2020

Поскольку вы не предоставили конкретные реализации двух данных лямбд, я хотел бы пояснить на простом примере:

Для вызова метода compute() нам нужны реализации BoolBiFunction и IntFunction

BoolBiFunction f = (p1, p2) -> p1>p2;
IntFunction g = p -> p*2;

Затем мы инициализируем x и intValues

x = 1;
intValues= {1, 3, 5};

Вызовите метод compute()

int result = compute(f, g, x);
System.out.println(result);

Выход:

16

Значения на каждом шаге for l oop:

value       x       f.apply(value,x)        g.apply(value)      result
1           1       false                   -                   0
3           1       true                    6                   0+6 = 6
5           1       true                    10                  6+10 = 16

В этом примере g.apply(value) возвращает value*2

Поскольку реализация Intfunction is p -> p*2

1 голос
/ 05 марта 2020

Проблема выглядит немного странной для меня. Но вот решение.

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

public class Temp {
    static int [] testData = {2, 5, 11, 2, 2, 7, 6, 3, 1, 9, 10, 6};

    public static void main(String [] args){
        answerToQuestion();
        //extraQuestionForYou();
    }

    public static void answerToQuestion(){
        //How many times does 2 occur in testData ? Answer is 3. Confirm it!

        IntData intFinder = new IntData(testData);
        int desiredNumber = 2;

        int times = intFinder
                //Find out how many times desiredNumber occurs in an array.
                .compute(
                //A function which tells me if one number is equal to another.
                (number1, number2) -> number1 == number2,
                //A function which says that it saw a number one more time, every time it sees that number.
                someNumber -> 1,
                //The number whose occurrence we want to find in an array.
                desiredNumber
                );

        //Testing - Runs only when assertions are enabled for your JVM. Set VM args = -ea for your IDE.
        assert times == 3 : "Expected " + desiredNumber + " to occur 3 times, but got " + times;
    }

}

Что происходит внутри функция вычисления?

f.apply (значение, х):

f = (number1, number2) -> number1 == number2.
f.apply(value, x) means number1 = value and number2 = x.

result = result + g.apply (значение) :

g = someNumber -> 1.
g.apply(value) means return 1 whenever you see value.

Мы можем повторно использовать метод compute () для выполнения других задач, например, для определения, сколько раз тройка заданного числа встречается в массиве, помимо того, что задал исходный вопрос. Есть два способа сделать это - использовать приведенный выше код и искать 6, ИЛИ использовать функцию bi, которая проверяет, является ли одно число тройным по отношению к другому. Мы используем последний подход в коде ниже. Вместо этого вы можете придумать лучший пример.

public static void extraQuestionForYou(){
    //How many times does triple of 2 occur in testData ? Answer is 2. Confirm it!

    IntData intFinder = new IntData(testData);
    int desiredNumber = 2;

    int times = intFinder
            //Find out how many times triple of desiredNumber occurs in an array.
            .compute(
                    //A function which tells me if one number is equal to triple of another.
                    (number1, number2) -> number1 * 3 == number2,
                    //A function which says that it saw a number one more time, every time it sees that number.
                    someNumber -> 1,
                    //The number whose "triples" we want to find in an array.
                    desiredNumber
            );

    //Testing - Runs only when assertions are enabled for your JVM. Set VM args = -ea for your IDE.
    assert times == 2 : "Expected " + desiredNumber + " to occur 2 times, but got " + times;
}
1 голос
/ 01 марта 2020

Ваш метод compute принимает BoolBiFunction, который проверяет, удовлетворяют ли два значения int некоторому условию. Если они удовлетворяют условию (т. Е. Если f.apply(value, x) равно true), результат применения IntFunction к текущему значению добавляется к итогу.

Если вы хотите, например, узнать, сколько элементов массива intValues равно 5, вам нужно позвонить:

IntData someObject = ...
int numberOf5s = someObject.compute((x,y) -> x == y,
                                    x -> 1,
                                    5);

Это означает, что BoolBiFunction вернет true тогда и только тогда, когда два int, переданные ему, равны.

IntFunction всегда вернет 1, поэтому он посчитает, сколько раз третий аргумент - 5 - находится в массиве intValues.

Учитывая вышеупомянутые параметры, переданные compute(), если мы заменим вызовы f.apply и g.apply фактическими телами соответствующих лямбда-выражений мы получим:

public int compute(BoolBiFunction f, IntFunction g, int x) {
    int result = 0;
    for (int value : intValues) {
        if (value == 5) { // which is equivalent to if (f.apply(value, x)) when x == 5
            result = result + 1; // which is equivalent to result = result + g.apply(value);
        }
    }
    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...