2010-04-08 14 views
10

Voglio implementare un metodo javascript come in java, è possibile?Function Object in Java

Di ', ho una classe Persona:

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

e un elenco con oggetti Person:

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

Voglio implementare un metodo come questo:

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

ModList riceve due parametri, uno è una lista, l'altro è l '"oggetto funzione", scorre la lista e applica questa funzione a ogni elemento nella lista. Nel linguaggio di programmazione funzionale, questo è facile, non so come faccia a fare questo java? Forse potrebbe essere fatto tramite proxy dinamico, questo ha un compromesso tra prestazioni e confronti rispetto al loop nativo?

+0

possibile duplicato di http: //stackoverflow.com/questions/122105/java-what-is-the-best-way-to-filter-a-collection –

+0

A un esame più attento: non è un duplicato, ma le risposte potrebbero comunque aiutarti. –

+0

Se vuoi quel tipo di potere, allora Groovy potrebbe valere la pena dare un'occhiata. In Groovy scrivi 'pList.each {it.age ++}' –

risposta

14

È possibile farlo con un'interfaccia e una classe interna anonima sua attuazione, come

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

Si noti che con varargs in Java5, la chiamata a Arrays.asList può essere semplificato come mostrato sopra.

Aggiornamento: Una versione generified di quanto sopra:

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

Nota che con la precedente definizione di modList, è possibile eseguire un Operation<Person> su esempio a List<Student> (fornito Student è una sottoclasse di Person). Un semplice tipo di parametro List<E> non lo consentirebbe.

+0

Buoni punti, quello di cui ho bisogno è un codice generato, valido per l'elenco . – Sawyer

+0

@Tony vedere il mio aggiornamento. –

+0

di ispirazione, grazie. – Sawyer

3

Dai uno sguardo al progetto lambdaj. Ecco un esempio dalla home page del progetto:

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

sì, ho già controllato il codice sorgente, voglio scrivere la mia versione di questo metodo di utilità. – Sawyer

+0

Link interessante, esattamente quello di cui ho bisogno per un mio progetto. Grazie! – Alfonso

2

Vedere google collections library. Guarda i metodi di trasformazione su Iterators e Iterables. Questo dovrebbe essere in grado di ottenere quello che vuoi.

+0

+1 per il collegamento Guava; biblioteca abbastanza ordinata, devo dare un'occhiata! –

0

Sì, questo è facile in un linguaggio di programmazione funzionale .. in Java è un po 'più complesso, ma si può lavorare fuori qualcosa di simile, utilizzando farmaci generici anche tipi quando possibile:

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

'Modificatore.modify' dovrebbe avere un parametro di tipo 'T' invece di' Transformable' per rendere i downcast inutili e aumentare la sicurezza del tipo. –