简体   繁体   中英

How do I pass a method as a parameter in Java 8?

I don't understand how to use lambdas to pass a method as a parameter.

Considering the following (not compiling) code, how can I complete it to get it work ?

public class DumbTest {
    public class Stuff {
        public String getA() {
            return "a";
        }
        public String getB() {
            return "b";
        }
    }

    public String methodToPassA(Stuff stuff) {
        return stuff.getA();
    }

    public String methodToPassB(Stuff stuff) {
        return stuff.getB();
    }

    //MethodParameter is purely used to be comprehensive, nothing else...
    public void operateListWith(List<Stuff> listStuff, MethodParameter method) {
        for (Stuff stuff : listStuff) {
            System.out.println(method(stuff));
        }
    }

    public DumbTest() {
        List<Stuff> listStuff = new ArrayList<>();
        listStuff.add(new Stuff());
        listStuff.add(new Stuff());

        operateListWith(listStuff, methodToPassA);
        operateListWith(listStuff, methodToPassB);
    }

    public static void main(String[] args) {
        DumbTest l = new DumbTest();

    }
}

Declare your method to accept a parameter of an existing functional interface type which matches your method signature:

public void operateListWith(List<Stuff> listStuff, Function<Stuff, String> method) {
    for (Stuff stuff : listStuff) {
        System.out.println(method.apply(stuff));
    }
}

and call it as such:

operateListWith(listStuff, this::methodToPassA);

As a further insight, you don't need the indirection of methodToPassA :

operateListWith(listStuff, Stuff::getA);

Your MethodParameter should be some interface you define with a single method. This is referred to as a functional interface. You can then pass your methods in. A quick demonstration:

public interface Test{
    void methodToPass(string stuff);
}

[...]

public class DumbTest{
     //MethodParameter is purely used to be comprehensive, nothing else...
    public void operateListWith(List<Stuff> listStuff, Test method) {
        for (Stuff stuff : listStuff) {
            System.out.println(method(stuff));
        }
    }
    public DumbTest() {
        List<Stuff> listStuff = new ArrayList<>();
        //fill list
        operateListWith(listStuff, methodToPassA);
        operateListWith(listStuff, methodToPassB);
    }
}

The definition of MethodParameter is missing from your source code. To be used with lambda expressions, it must be a functional interface, for example:

@FunctionalInterface
interface MethodParameter {
    String apply(Stuff input);
}

(The @FunctionalInterface annotation is optional.)

To use the method, you have call the method from the interface:

System.out.println(method.apply(stuff));

And thirdly, a method reference always needs a context. In your case you have to do:

operateListWith(listStuff, this::methodToPassA);
operateListWith(listStuff, this::methodToPassB);

You need to use method references.

You don't need to create a method like operateListWith , that's sort of the whole idea. Instead, you can operate on each value using forEach by doing something like this:

listStuff.stream.forEach(object::methodToPassA);

For example:

public class StreamExample {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("Hello", "What's Up?", "GoodBye");
    list.stream().forEach(System.out::println);
  }
}

Output:

Hello
What's Up?
GoodBye

In your case, you can get the value inside Stuff using .map , and then operate on it using forEach , like this:

public class DumbTest {
  public class Stuff {
    public String getA() {
      return "a";
    }

    public String getB() {
      return "b";
    }
  }

  public String methodToPassA(Stuff stuff) {
    return stuff.getA();
  }

  public String methodToPassB(Stuff stuff) {
    return stuff.getA();
  }

  public DumbTest() {
    List<Stuff> listStuff = Arrays.asList(new Stuff(), new Stuff());

    listStuff.stream()
        .map(this::methodToPassA)
        .forEach(System.out::println);
  }

  public static void main(String[] args) {
    DumbTest l = new DumbTest();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM