Reputation: 2633
I have a large number of methods that need to be applied to each member of a given arrayList. The problem is that I'm at compile time uncertain which methods need to be applied to the arrayList and applying all of them each time (with a check) would be to costly (realtime application). So I'm now looking for a way to give the list a number of methods (a la function programming) and have them run. I know I could create special classes where each class uses only a uses a single method on each of it's members but there are roughly 50 methods so that would quickly escalate into 50 different classes. Which would add a lot of unnecessary complexity to the project. Is there another way?
So what I'm looking for is something like this:
public void runMethode(Function f,ArrayList<ObjectWithF> al){
for(ObjectWithF o:al){
o.f();
}
}
Does such a thing exist in java? Or am I going to have to either call all 50 methods or create 50 different classes? Or would a wrapper pattern work here?
Upvotes: 2
Views: 2612
Reputation: 54659
In Java 8, this functionality is provided via the Stream#forEach(Consumer) method in a very convenient form.
If you don't have Java 8 yet, then you can create an interface, and create instances of anonymous classes implementing this interface. This is a bit more verbose, but still better than 50 named classes.
It may be beneficial to design this interface in a way that is structurally equal to the Consumer
interface that is used in Java 8, so that it may simply be changed to use the Java 8 version once you do the update.
This example shows a comparison of both approaches:
import java.util.ArrayList;
import java.util.List;
class Person
{
void sayHello()
{
System.out.println("Hello from "+this);
}
void sayGoodbye()
{
System.out.println("Goodbye from "+this);
}
}
// This interface already exists as java.util.function.Consumer in Java 8
interface Consumer<T>
{
void accept(T t);
}
public class ForEachTest
{
public static void main(String[] args)
{
List<Person> persons = new ArrayList<Person>();
for (int i=0; i<5; i++)
{
persons.add(new Person());
}
runJava8(persons);
runJava7(persons);
}
private static void runJava8(List<Person> persons)
{
persons.stream().forEach(Person::sayHello);
persons.stream().forEach(Person::sayGoodbye);
}
private static void runJava7(List<Person> persons)
{
runMethodJava7(persons, new Consumer<Person>()
{
@Override
public void accept(Person person)
{
person.sayHello();
}
});
runMethodJava7(persons, new Consumer<Person>()
{
@Override
public void accept(Person person)
{
person.sayGoodbye();
}
});
}
public static void runMethodJava7(
List<Person> persons, Consumer<? super Person> consumer)
{
for(Person person : persons)
{
consumer.accept(person);
}
}
}
Upvotes: 3
Reputation: 7461
As of Java 8, use may use Consumer
class:
public void runMethod(Consumer<ObjectWithF> consumer, ArrayList<ObjectWithF> al) {
for (ObjectWithF o : al) {
consumer.accept(o);
}
}
...
// for example
runMethod (o -> System.out.println (o), listOfObjectsWithF);
// or
runMethod (System.out::println, listOfObjectsWithF);
// or even
listOfObjectsWithF.forEach(System.out::println);
If it's not Java8, you may create this interface
yourself and realize it for every method:
interface Consumer {
public void apply(ObjectWithF o);
}
public void runMethod(Consumer consumer, ArrayList<ObjectWithF> al) {
for (ObjectWithF o : al) {
consumer.apply(o);
}
}
...
runMethod(new Consumer() {
public void apply(ObjectWithF o) {
//for example
System.out.println (o.toString());
}
}, listOfObjectsWithF);
Upvotes: 1
Reputation: 74
reflect can help.
see the code blow : String obj = "abc";
String methodName = "toString";
try {
Method method = obj.getClass().getMethod("toString");
System.out.println(method.invoke(obj));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
we have a obj, and given a method, we can run this method on that object.
And, you can also consider define a interface, and all your objects in the list implements the interface. and iterate the list, call those methods which defined in the interface.
Upvotes: 1