Supposons que j'ai une liste de voitures:
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());
}
Comment puis-je raccourcir le code ci-dessus? En un mot, comment puis-je appeler une méthode sur chaque élément d'une liste?
Par exemple, en Python:
[car.name for car in cars]
METTRE À JOUR:
Voir answer de aaiezza pour une solution Java 8 utilisant une expression lambda.
Réponse originale antérieure à Java 8:
L’effet peut être obtenu avec Guava, l’implémentation Function
est déjà plus détaillée que ce que vous avez:
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);
(N'oubliez pas que Lists.transform
renvoie une vue qui appliquera la fonction paresseusement. Si vous souhaitez une copie immédiate, vous devez copier la liste renvoyée dans une nouvelle liste.)
Cela ne vous aide donc pas à raccourcir votre code, mais constitue un exemple de la manière dont il est détaillé pour obtenir l'effet recherché en Java.
Edit: Vous pouvez jeter un oeil sur lambdaj , une bibliothèque qui semble s’approcher de ce que vous recherchez. Je n'ai pas essayé cela moi-même, mais la page d'accueil montre cet exemple:
List<Person> personInFamily = asList(new Person("Domenico"), new Person("Mario"), new Person("Irma"));
forEach(personInFamily).setLastName("Fusco");
Java 8 aura (espérons-le) une forme d'expression lambda, ce qui rendra un code comme celui-ci plus réalisable. (La question de savoir s'il y aura une compréhension de liste est une autre affaire.)
Votre souhait a été exaucé!
---MODIFIER---
lol comme au bon moment: forEach ()
Vérifiez certainement ceci.
Pour votre question en particulier, cela devient le suivant:
// 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()) );
C'est vraiment incroyable ce qu'ils ont fait ici. Je suis excité de voir cela utilisé dans le futur.
---MODIFIER---
J'aurais dû le voir plus tôt mais je ne peux pas résister mais poster à ce sujet.
La fonctionnalité Stream ajoutée à jdk8 permet d'utiliser la méthode map .
// 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() );
autre que de supprimer les accolades et/ou de déplacer tout le code sur une seule ligne, ce qui peut ne pas être une bonne idée, vous ne pouvez pas.
Dans common-LISP, il existe une fonction mapcar (cela n'a rien à voir avec l'exemple car ci-dessus) . Une fonction mapcar générale en 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());
}
Pour la voiture-exemple:
List<String> carNames = mapcar(cars, car -> car.getName());
Si vous êtes bloqué et devez toujours utiliser Apache Commons, la classe Transformer peut vous aider: http://apachecommonstipsandtricks.blogspot.de/2009/01/examples-of-functors-transformers.html