2

I have a method that accepts a few Functional Interfaces which works fine when invoked using lambda expressions.

However when I try the same syntax from the main method providing the lambda expression inline (rather than defining an instance of it and invoking the method as in the first case), it gives me a syntax error. What am I missing?

Here is the code

    package test.lambdas;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class Person {

    private String givenName;
    private String surName;
    private int age;

    public String getGivenName() {
        return givenName;
    }
    public Person setGivenName(String givenName) {
        this.givenName = givenName;
        return this;
    }
    public String getSurName() {
        return surName;
    }
    public Person setSurName(String surName) {
        this.surName = surName;
        return this;
    }
    public int getAge() {
        return age;
    }
    public Person setAge(int age) {
        this.age = age;
        return this;
    }
    public String getGender() {
        return gender;
    }
    public Person setGender(String gender) {
        this.gender = gender;
        return this;
    }
    public String geteMail() {
        return eMail;
    }
    public Person seteMail(String eMail) {
        this.eMail = eMail;
        return this;
    }
    public String getPhone() {
        return phone;
    }
    public Person setPhone(String phone) {
        this.phone = phone;
        return this;
    }
    public String getAddress() {
        return address;
    }
    public Person setAddress(String address) {
        this.address = address;
        return this;
    }
    private String gender;
    private String eMail;
    private String phone;
    private String address;

    public String toString(){
        return givenName;
    }


    static void print(List<Person> l, Predicate<Person> p, Function<Person, String> f, Consumer<String> c){
        for(Person p1 : l){
            if(p.test(p1)){
                c.accept(f.apply(p1));
            }
        }
    }

    public static List<Person> getPersons(){
        List<Person> lp = new ArrayList<>();
        Person p = new Person();
        p.setGivenName("X").setSurName("Y").setAge(15).seteMail("[email protected]").setGender("Male").setAddress("Test Location");
        Person p1 = new Person();
        p1.setGivenName("A").setSurName("B").setAge(34).seteMail("[email protected]").setGender("Male").setAddress("Test Location1");
        Person p2 = new Person();
        p2.setGivenName("M").setSurName("N").setAge(33).seteMail("[email protected]").setGender("Male").setAddress("Test Location2");      
        lp.add(p);lp.add(p1);lp.add(p2);        
        return lp;
    }

    public static void main(String[] args) {
        List<Person> l = getPersons();

        Predicate<Person> p = p1 -> p1.getAge() > 18;
        Function<Person, String> f = p2 -> p2.geteMail();
        Consumer<String> c = p3 -> System.out.println("Email  "+p3+" is a major");

        print(l, p, f, c); //this works fine

        //lets do it inline
        for(Person p1 : l){     
            c.accept(f.apply(p1 -> p1.getAge() > 18)); //this throws error detailed below   
        }
    }
}

The line

c.accept(f.apply(p1 -> p1.getAge() > 18));

throws the following error

  1. at f.apply => The method apply(Person) in the type Function is not applicable for the arguments (( p1) -> {})

  2. (at p1 -> p1.getAge() > 18) => The target type of this expression must be a functional interface

    c.accept() accepts a String which it prints out. f.apply() accepts a Person and returns a String (his email) which c.accept prints out. I know my attempt at providing (p1 -> p1.getAge()> 18) to f.apply() is wrong. My question is how do I recreate the static print method inline or it is not possible to do so?

0

1 Answer 1

1

change:

c.accept(f.apply(p1 -> p1.getAge() > 18));

to:

c.accept(f.apply(p1));

This is because the function f takes a Person not a function.

edit:

if you want to replicate what the print method does inline then you can do:

l.stream().filter(p).forEach(p1 -> c.accept(f.apply(p1)));
Sign up to request clarification or add additional context in comments.

7 Comments

No, in this case, the condition specified in (p1 -> p1.getAge() > 18) cannot be applied. Just change the age of one of the Person object to 15 and you will see that the static method filters out that person. However if I apply p1 as suggested, it will print out all the person objects. Edit::: I have just made the change to update one of the Person age to 15 to demonstrate what I am saying.
@ramp try l.stream().filter(p).forEach(p1 -> c.accept(f.apply(p1)));
that works - thanks. It uses the aggregate functions on collections. I will mark that as an accepted answer if there are no other responses. Basically I wanted to confirm that, with plain lambda expressions, there is no other option than to enclose the functionality in a method and invoke that.
l.stream().filter(p).forEach(p1 -> c.accept(f.apply(p1))); can be simplified to l.stream(p).map(f).forEach(c);
@Aominè sorry my bad, i meant l.stream().filter(p).map(f).forEach(c);
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.