2011-08-28 3 views
23

Supponiamo che ho una lista di vetture:Come posso chiamare un metodo su ciascun elemento di un elenco?

public class Car { 
    private String brand; 
    private String name; 
    private String color; 

    public Car() { // ... } 

    public getName() { return name; } 
    // ... 
} 

// Suppose that I have already init the list of car 
List<Car> cars = //... 
List<String> names = new ArrayList<String>(); 


for (Car c : cars) { 
    names.add(c.getName()); 
} 

Come posso accorciare il codice di cui sopra? In poche parole, come posso chiamare un metodo su ciascun elemento di un elenco?

Per esempio, in Python:

[car.name for car in cars] 

risposta

17

UPDATE:

di answer per una soluzione di 8 Java utilizzando un'espressione lambda See scribaniwannabe.

originale pre-Java 8 risposta:

L'effetto può essere ottenuto con Guava, l'attuazione Function è già più dettagliato di quello che hai:

List<Car> cars = //... 

Function<Car, String> carsToNames = new Function<Car, String>() { 
    @Override 
    public String apply(Car car) { 
     return car.getName(); 
    } 
} 

List<String> names = Lists.transform(cars, carsToNames); 

(Tenete a mente che Lists.transform restituisce una vista che applicherà la funzione pigramente - se si desidera una copia immediata, è necessario copiare la lista restituita in una nuova lista.)

Quindi questo fa non ti aiuta ad abbreviare il tuo codice, ma è un esempio di quanto sia verboso raggiungere l'effetto desiderato in Java.

Modifica: Si potrebbe dare un'occhiata a lambdaj, una libreria che sembra avvicinarsi a ciò che stai cercando. Non ho provato questo fuori me stesso, ma la home page mostra questo esempio:

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

diverso sbarazzarsi delle parentesi graffe e/o spostare tutto il codice di una linea, che potrebbe non essere una buona idea, non è possibile.

38

Java 8 (si spera) avrà qualche forma di espressione lambda, che renderà il codice come questo più fattibile. (Se ci sarà qualcosa come la comprensione delle liste è un'altra questione.)

Il tuo desiderio è stato concesso!

--- EDIT ---
lol come a un segnale: forEach()

Sicuramente controllare questo fuori.

per la tua domanda specifica, diventa il folowing:

// Suppose that I have already init the list of car 
List<Car> cars = //... 
List<String> names = new ArrayList<String>(); 

// LAMBDA EXPRESSION 
cars.forEach((car) -> names.add(car.getName())); 

E 'davvero molto incredibile quello che hanno fatto qui. Sono eccitato di vedere questo usato in futuro.

--- EDIT ---
Avrei dovuto vederlo prima, ma non posso resistere ma postare su di esso.

La funzionalità Stream aggiunta in jdk8 consente lo map method.

// Suppose that I have already init the list of car 
List<Car> cars = //... 

// LAMBDA EXPRESSION 
List<String> names = cars.stream().map(car -> car.getName()).collect(Collectors.toList()); 
+1

Oh lambda, è la bellezza! –

+1

@ EM-Creations Non è lei però ... – aaiezza

0

In common-lisp c'è un mapcar-funzione (questo non ha nulla a che fare con l'auto-nell'esempio precedente). Un mapcar-funzione generale in Java:

static <LIST_TYPE, ELEM_TYPE> List<LIST_TYPE> mapcar(Collection<ELEM_TYPE> list, Function<ELEM_TYPE, LIST_TYPE> function) 
{ 
    return list.stream().map(function).collect(Collectors.toList()); 
} 

Per l'auto-example:

List<String> carNames = mapcar(cars, car -> car.getName());