Java 中的函数对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2599698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:58:50  来源:igfitidea点击:

Function Object in Java

java

提问by Sawyer

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

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

Say , I have a Person class :

说,我有一个 Person 类:

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

And a list with Person objects:

还有一个包含 Person 对象的列表:

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 ?

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

回答by Péter T?r?k

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.asListcan be simplified as shown above.

请注意,使用 Java5 中的可变参数,Arrays.asList可以简化对 的调用,如上所示。

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 Studentis a subclass of Person). A plain List<E>parameter type would not allow this.

请注意,使用 的上述定义modList,您也可以Operation<Person>在例如 a 上执行List<Student>(前提Student是是 的子类Person)。普通List<E>参数类型不允许这样做。

回答by Andrea Polci

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

看看lambdaj项目。这是项目主页上的示例:

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

回答by Russell Leggett

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.

查看谷歌收藏库。查看 Iterators 和 Iterables 上的转换方法。那应该能够让你得到你想要的。

回答by Hyman

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:

是的,这在函数式编程语言中很容易......在 Java 中它有点复杂,但你可以解决这样的问题,在可能的情况下也使用泛型类型:

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

回答by Raging Goblin

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 +
            '}';
    }
}