Java中的函数对象

我想在java中实现类似javascript的方法,这可能吗?

说,我有一个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 pList = Arrays.asList(new Person[] {p1,p2}); 

我想实现这样的方法:

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

modList接收两个参数,一个是列表,另一个是“函数对象”,它循环列表,并将此函数应用于列表中的每个元素。 在函数式编程语言中,这很容易,我不知道java怎么做到这一点? 也许可以通过动态代理完成,与原生for循环相比,它是否有性能折衷?

您可以使用接口和实现它的匿名内部类来完成它,例如

 Person p1 = new Person("Jenny",20); Person p2 = new Person("Kate",22); List pList = Arrays.asList(p1, p2); interface Operation { abstract void execute(Person p); } public void modList(List list, Operation op) { for (Person p : list) op.execute(p); } modList(pList, new Operation { public void execute(Person p) { p.setAge(p.getAge() + 1)}; }); 

请注意,对于Java5中的varargs,可以简化对Arrays.asList的调用,如上所示。

更新:上述的一般版本:

 interface Operation { abstract void execute(E elem); } public  void modList(List list, Operation op) { for (E elem : list) op.execute(elem); } modList(pList, new Operation() { public void execute(Person p) { p.setAge(p.getAge() + 1); } }); 

请注意,使用上面的modList定义,您也可以在例如List上执行Operation (假设StudentPerson的子类)。 普通的List参数类型不允许这样做。

看看lambdaj项目。 以下是项目主页的示例:

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

看看google集合库 。 查看Iterators和Iterables上的转换方法。 那应该能够得到你想要的东西。

是的,这在函数式编程语言中很容易..在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 { void modify(Transformable object); } static class AgeIncrementer implements Modifier { public void modify(Transformable p) { ++((Person)p).age; } } static void applyOnList(List objects, Modifier modifier) { for (Transformable o : objects) { modifier.modify(o); } } public static void main(String[] args) { ArrayList l = new ArrayList(); 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); } } 
 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 pList = Arrays.asList(new Person[]{p1, p2}); Function, List> theFunction = Function.>identity() .andThen(personList -> personList .stream() .map(person -> new Person(person.getName(), person.getAge() + 1)) .collect(Collectors.toList())); // You can use this directly List directly = theFunction.apply(pList); directly.forEach(person -> System.out.println(person)); // Or use it as an input parameter List toMethod = modList(pList, theFunction); toMethod.forEach(person -> System.out.println(person)); // Or you might prefer this way List 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 modList(List personList, Function, List> 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 + '}'; } }