Thijser
Thijser

Reputation: 2633

java run method on every element of arraylist

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

Answers (3)

Marco13
Marco13

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

Dmitry Ginzburg
Dmitry Ginzburg

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

ThinkingQuest
ThinkingQuest

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

Related Questions