10

I wanna implement a javascript like method in java , is this possible ?

Say , I have a Person class :

public class Person {
 private String name ;
 private int age ;
 // constructor ,accessors are omitted
}

And a list with Person objects:

Person p1 = new Person("Jenny",20);
Person p2 = new Person("Kate",22);
List<Person> pList = Arrays.asList(new Person[] {p1,p2});

I wanna implement a method like this:

modList(pList,new Operation (Person p) {
  incrementAge(Person p) { p.setAge(p.getAge() + 1)};
});

modList receives two params , one is a list , the other is the "Function object", it loops the list ,and apply this function to every element in the list. In functional programming language,this is easy , I don't know how java do this? Maybe could be done through dynamic proxy, does that have a performance trade off compares to native for loop ?

5
  • possible duplicate of stackoverflow.com/questions/122105/… Commented Apr 8, 2010 at 12:25
  • On closer inspection: it's not a duplicate, but the answers might still help you. Commented Apr 8, 2010 at 12:26
  • If you want that kind of power, then Groovy might be worth a look. In Groovy you'd write pList.each { it.age++ } Commented Apr 8, 2010 at 12:36
  • I guess scala could also do it. But I code for my company, not myself. Commented Apr 8, 2010 at 12:37
  • See also stackoverflow.com/q/122407/545127 Commented Feb 25, 2013 at 13:56

5 Answers 5

14

You can do it with an interface and an anonymous inner class implementing it, like

Person p1 = new Person("Jenny",20);
Person p2 = new Person("Kate",22);
List<Person> pList = Arrays.asList(p1, p2);

interface Operation {
  abstract void execute(Person p);
}

public void modList(List<Person> list, Operation op) {
  for (Person p : list)
    op.execute(p);
}

modList(pList, new Operation {
  public void execute(Person p) { p.setAge(p.getAge() + 1)};
});

Note that with varargs in Java5, the call to Arrays.asList can be simplified as shown above.

Update: A generified version of the above:

interface Operation<E> {
  abstract void execute(E elem);
}

public <E> void modList(List<? extends E> list, Operation<E> op) {
  for (E elem : list)
    op.execute(elem);
}

modList(pList, new Operation<Person>() {
    public void execute(Person p) { p.setAge(p.getAge() + 1); }
});

Note that with the above definition of modList, you can execute an Operation<Person> on e.g. a List<Student> too (provided Student is a subclass of Person). A plain List<E> parameter type would not allow this.

Sign up to request clarification or add additional context in comments.

1 Comment

Good points, what I need is a generified code , that applies to List<?>.
3

Take a look at the lambdaj project. Here is an example from the project home page:

List<Person> personInFamily = asList(new Person("Domenico"), new Person("Mario"), new Person("Irma"));
forEach(personInFamily).setLastName("Fusco");

2 Comments

yeah, I've already checked out the source code, I want to write my own version of this utility method.
Interesting link, exactly what I need for a project of mine. Thanks!
2

Look at the google collections library. Look at the transform methods on Iterators and Iterables. That should be able to get you what you want.

1 Comment

+1 for Guava link; pretty neat library, I gotta check it out!
1

Yes, this is easy in a functional programming language.. in Java it's a little more complex but you can work out something like this, using also generics types when possible:

public class TestCase {
    static interface Transformable {};

    static class Person implements Transformable {
        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String name;
        public int age;
    }

    static interface Modifier<T extends Transformable> {
        void modify(Transformable object);
    }

    static class AgeIncrementer implements Modifier<Person> {
        public void modify(Transformable p) {
            ++((Person)p).age;
        }
    }

    static void applyOnList(List<? extends Transformable> objects, Modifier<? extends Transformable> modifier) {    
        for (Transformable o : objects) {
            modifier.modify(o);
        }
    }

    public static void main(String[] args) {
        ArrayList<Person> l = new ArrayList<Person>();
        l.add(new Person("John", 10));
        l.add(new Person("Paul", 22));
        l.add(new Person("Frank", 35));

        applyOnList(l, new AgeIncrementer());

        for (Person p : l)
            System.out.println(p.age);
    }
}

1 Comment

Modifier.modify should have a parameter of type T instead of Transformable to make downcasts unnecessary and increase type safety.
0
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FuntionAsParameter {


    public static void main(final String[] args) {

        Person p1 = new Person("Jenny", 20);
        Person p2 = new Person("Kate", 22);

        List<Person> pList = Arrays.asList(new Person[]{p1, p2});

        Function<List<Person>, List<Person>> theFunction = Function.<List<Person>>identity()
            .andThen(personList -> personList
                .stream()
                .map(person -> new Person(person.getName(), person.getAge() + 1))
                .collect(Collectors.toList()));

        // You can use this directly
        List<Person> directly = theFunction.apply(pList);
        directly.forEach(person -> System.out.println(person));

        // Or use it as an input parameter
        List<Person> toMethod = modList(pList, theFunction);
        toMethod.forEach(person -> System.out.println(person));

        // Or you might prefer this way
        List<Person> thirdWay = modList(pList,
                (list) -> list.stream()
                        .map(person -> new Person(person.getName(), person.getAge() + 1))
                        .collect(Collectors.toList())
        );
        thirdWay.forEach(person -> System.out.println(person));
    }

    private static List<Person> modList(List<Person> personList, Function<List<Person>, List<Person>> theFunction) {
        return theFunction.apply(personList);
    }


}

class Person {

    private String name;
    private int age;

    public Person(final String name, final int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

Comments

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.