1

My collect() function calls Foo.f(). I would like to make Foo.f() itself a parameter of my function. Is this possible in Java?

  • How can I pass either Foo.f() or Foo.g() (or any other function of Foo that returns a String) to my function?
  • Is there an already existing function which walks a collection and collects the result of calling a method of every collection item?

.

class Foo {
    public String f() { return "f"; }
    public String g() { return "g"; }
    // ...
}

public List<String> collect(List<Foo> foos)
{
    List<String> result = new ArrayList<String>();

    for (final Foo foo: foos) {
        result.add(foo.f());  // I want Foo.f to be a parameter
    }

    return result;
}

Update

I would like to point out the fact that I am not merely calling the same function but rather the member function f for all items of the List<Foo> collection.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137

4 Answers4

8

In Java 8, you can do

collect(foos, Foo::f);

public List<String> collect(List<Foo> foos, Function<Foo,String> func)
{
    List<String> result = new ArrayList<String>();

    for (final Foo foo: foos) {
        result.add(func.apply(foo));
    }

    return result;
}

Or with steam API

Stream<Foo> foos = ...;
Stream<String> strs = foos.map(Foo::f);
Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
irreputable
  • 44,725
  • 9
  • 65
  • 93
  • Java 8 is not exactly stable yet. In earlier versions of Java, closures and function pointers are not supported. – RudolphEst Mar 05 '13 at 16:27
  • @RudolphEst But if you were asking this question, you probably aren't going to be producing much software for a while. Might as well use Java SE 8 now. / Java SE 8 does not have function pointers, and "lambdas" aren't really any more of a closure than anonymous inner classes (the point being that the syntax is less verbose). – Tom Hawtin - tackline Mar 05 '13 at 16:43
  • @TomHawtin-tackline It depends. If the OP is a student at university, he might be constrained to use Java 7 in his projects. – RudolphEst Mar 05 '13 at 16:51
5

You can use interfaces

  interface Foo
  {
      String fn();
  }

and pass the interface to the method

 void anyMethod(Foo f)
 {
   f.fn();
 }

you dont need to create a concrete Foo, just create Foo anonymously

  new Foo() {

  @Override
  public String fn()
  {
   return "something";
  }
};

In Java 8 you don't need to anonymously implement the interface. You could use a lambda expression instead.

  anyMethod(()-> "something");
Sleiman Jneidi
  • 22,907
  • 14
  • 56
  • 77
0

In Java you are not supposed to pass method as a parameter, but you can pass an object as parameter.

It is called Strategy Pattern, you would need to use interface.

Nikolay Kuznetsov
  • 9,467
  • 12
  • 55
  • 101
0

You can use an interface like:

interface IFoo {
    String getString();
}

Then implement it in the custom ways:

class F implements IFoo {
    public String getString() {
        return "f";
    }
}

class G implements IFoo {
    public String getString() {
        return "g";
    }
}

And have your function take a list of anything that implements IFoo:

public List<String> collect(List<? extends IFoo> foos)
{
    List<String> result = new ArrayList<String>();

    for (final IFoo foo: foos) {
        result.add(foo.getString());
    }

    return result;
}

Usage:

for (String a : collect(Arrays.asList(new F(), new G()))) {
    System.out.println(a);
}
    //Prints f and g
Esailija
  • 138,174
  • 23
  • 272
  • 326