Функциональный объект в Java

Я хочу реализовать javascript-метод в java, возможно ли это?

Скажем, у меня есть класс Person:

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

И список с объектами Person:

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

Я хочу реализовать такой метод:

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

modList получает два параметра, один - список, другой - "Объект функции", он перебирает список и применяет эту функцию к каждому элементу в списке. На языке функционального программирования это легко, я не знаю, как это сделать java? Может быть, это можно сделать с помощью динамического прокси-сервера, имеет ли отношение производительности к сравнению с native для цикла?

Ответ 1

Вы можете сделать это с помощью интерфейса и анонимного внутреннего класса, реализующего его, например

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)};
});

Обратите внимание, что с помощью varargs в Java5 вызов Arrays.asList может быть упрощен, как показано выше.

Обновление: Обобщенная версия выше:

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); }
});

Обратите внимание, что с приведенным выше определением modList вы можете выполнить Operation<Person>, например. a List<Student> тоже (если Student является подклассом Person). Обычный тип параметра List<E> не позволяет этого.

Ответ 2

Взгляните на проект lambdaj. Вот пример с домашней страницы проекта:

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

Ответ 3

Посмотрите библиотеку коллекций google. Посмотрите на методы преобразования на Iterators и Iterables. Это должно быть в состоянии получить то, что вы хотите.

Ответ 4

Да, это просто на функциональном языке программирования.. в Java это немного сложнее, но вы можете что-то с этим поработать, используя также типы generics, когда это возможно:

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);
    }
}