web-dev-qa-db-fra.com

Comment puis-je appeler une méthode sur chaque élément d'une liste?

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]
32
Sandro Munda

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");
20
Paul Bellora

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() );
56
aaiezza

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. 

2
hvgotcodes

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());
0
Ben Janus

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

0
Marek Puchalski