2010-04-08 10 views
10

Ich möchte eine JavaScript-ähnliche Methode in Java implementieren, ist das möglich?Funktion Objekt in Java

Sag mal, habe ich eine Klasse Person:

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

und eine Liste mit Person-Objekte:

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

Ich möchte eine Methode wie folgt implementieren:

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

ModList erhält Zwei Parameter, einer ist eine Liste, der andere ist das "Function-Objekt", es führt eine Schleife durch die Liste und wendet diese Funktion an jedes Element in der Liste. In der funktionalen Programmiersprache ist das einfach, ich weiß nicht, wie Java das macht? Vielleicht könnte durch dynamische Proxy getan werden, hat das eine Leistungsabrechnung im Vergleich zu nativen for-Schleife?

+0

möglich Duplikat http: //stackoverflow.com/questions/122105/java-what-is-the-best-way-to-filter-a-collection –

+0

Bei näherer Betrachtung: Es ist kein Duplikat, aber die Antworten können Ihnen immer noch helfen. –

+0

Wenn Sie diese Art von Power wollen, dann könnte Groovy einen Blick wert sein. In Groovy schreibst du 'pList.each {it.age ++}' –

Antwort

14

Sie können es mit einer Schnittstelle und einer anonymen inneren Klasse Durchführung, wie

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

Beachten Sie, dass mit varargs in Java5, den Aufruf Arrays.asList kann wie oben gezeigt vereinfacht werden.

Update: A generified Version des obigen:

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

Beachten Sie, dass mit der obigen Definition von modList, können Sie eine Operation<Person> auf z ausführen a List<Student> auch (vorausgesetzt, Student ist eine Unterklasse von Person). Ein einfacher List<E> Parametertyp würde dies nicht erlauben.

+0

Gute Punkte, was ich brauche, ist ein generierter Code, der für die Liste gilt. – Sawyer

+0

@Tony sehe mein Update. –

+0

inspirierend, danke. – Sawyer

3

Werfen Sie einen Blick auf das Projekt lambdaj. Hier ist ein Beispiel aus der Projekt-Homepage:

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

Ja, ich habe bereits den Quellcode ausgecheckt, ich möchte meine eigene Version dieser Utility-Methode schreiben. – Sawyer

+0

Interessanter Link, genau das, was ich für ein Projekt von mir brauche. Vielen Dank! – Alfonso

2

Schauen Sie sich die google collections library an. Sehen Sie sich die Transformationsmethoden für Iteratoren und Iterables an. Das sollte in der Lage sein, dich zu bekommen, was du willst.

+0

+1 für Guava-Link; ziemlich ordentliche Bibliothek, ich muss es überprüfen! –

0

Ja, das ist einfach in einer funktionalen Programmiersprache .. in Java, es ist ein wenig komplexer, aber Sie können so etwas wie dies funktionieren, auch Typen Verwendung von Generika, wenn möglich:

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

'Modifikator.modify' sollte einen Parameter vom Typ 'T' anstelle von' Transformable' haben, um Downcasts überflüssig zu machen und die Typsicherheit zu erhöhen. –