Calling a method from the result of a lambda function

I have an object ( Adult

) with another object ( Child

) as a parameter. I am trying to write Function

which will return a child name if provided by an adult.

I wrote this:

public static void main(String[] args) {
    Function<Adult, Object> adult_name_f = Adult::getName;
    Function<Adult, Object> adult_child_f = Adult::getChild;
    Function<Adult, Object> child_name_f = Adult::getChild.getName;
}

static class Adult {
    String name;
    Child child;

    public Child getChild() {
        return child;
    }

    public String getName() {
        return name;
    }
}

static class Child {
    String name;

    public String getName() {
        return name;
    }
}

      

but (obviously) Adult::getChild.getName

invalid Function

.

Is there a way to return the child's name if specified by an adult?

+3


source to share


2 answers


First, you must specify the appropriate return type Function

.

Function<Adult, String> adult_name_f = Adult::getName;
Function<Adult, Child> adult_child_f = Adult::getChild;

      

Then you can use the method Function.andThen()

to create the third one Function

.

Function<Adult, String> child_name_f = adult_child_f.andThen(Child::getName);

      



Alternatively, and most often for chaining methods, you can define Function

using a lambda expression. You can even use lambda expressions for the first two, but method reference is better (less generated code).

Function<Adult, String> adult_name_f = a -> a.getName();
Function<Adult, Child> adult_child_f = a -> a.getChild();
Function<Adult, String> child_name_f = a -> a.getChild().getName();

      

Test

Adult mary = new Adult("Mary", new Child("Jesus"));
System.out.println(adult_name_f.apply(mary));  // prints: Mary
System.out.println(adult_child_f.apply(mary)); // prints: Test$Child@XXXXXXXX
System.out.println(child_name_f.apply(mary));  // prints: Jesus

      

+4


source


The easiest way is to just use lambda.

Function<Adult, Object> child_name_f = adult -> adult.getChild().getName();

      

Note that this is the syntax for what Java calls "lambda". The syntax you used in your question is a method reference, not a lambda, but the two are closely related. A method reference can always be expressed as a lambda. Thus:

Function<Adult, Object> adult_name_f = Adult::getName;

      

equivalent to



Function<Adult, Object> adult_name_f = adult -> adult.getName();

      

[There may be differences in how they are implemented, but the effect is the same for all practical purposes.]

If you want to call two methods, there is no easy way to do it using the method reference syntax, but the lambda works just fine.

See How do I compose functions? for some other ideas on how you can create a function composition from two method references. I think these answers are interesting, but in real life I still use lambda.

+3


source







All Articles