Как я могу вызвать метод для каждого элемента списка? - PullRequest
35 голосов
/ 28 августа 2011

Предположим, у меня есть список автомобилей:

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

Как мне сократить указанный выше код? В двух словах, как я могу вызвать метод для каждого элемента списка?

Например, в Python:

[car.name for car in cars]

Ответы [ 5 ]

61 голосов
/ 19 декабря 2013

Java 8 будет (надеюсь) иметь некоторую форму лямбда-выражения, которая сделает такой код более выполнимым.(Будет ли что-нибудь подобное списковому пониманию - другое дело.)

Ваше желание было удовлетворено!

--- EDIT ---LOL, как будто на реплике: forEach ()

Определенно проверьте это.

Для вашего вопроса конкретно, это становится следующим:

// 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()) );

Это действительно невероятно, что они сделали здесь.Я рад видеть это в будущем.

--- EDIT ---Я должен был увидеть это раньше, но я не могу удержаться, кроме как написать об этом.

Функциональность Stream, добавленная в jdk8, позволяет использовать метод 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() );

Еще более кратким было бы использование ссылок на методы Java 8 ( oracle doc ).

List<String> names = cars.stream().map( Car::getName ).collect( Collectors.toList() );
21 голосов
/ 28 августа 2011

UPDATE:

См. Ответ aaiezza для решения Java 8 с использованием лямбда-выражения.

Оригинальный ответ до Java 8:

Эффект может быть достигнут с помощью Guava, реализация Function уже более многословна, чем у вас:

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

(Имейте в виду, что Lists.transform возвращает представление, которое будет применять функцию лениво - если вы хотите немедленное копирование, вам необходимо скопировать возвращенный список в новый список.)

Так что это не поможет вам сократить ваш код, но это пример того, насколько многословно это для достижения желаемого эффекта в Java.

Редактировать: Вы можете взглянуть на lambdaj , библиотеку, которая, кажется, подходит к тому, что вы ищете. Я сам не пробовал, но на домашней странице показан пример:

List<Person> personInFamily = asList(new Person("Domenico"), new Person("Mario"), new Person("Irma"));
forEach(personInFamily).setLastName("Fusco");
2 голосов
/ 28 августа 2011

кроме как избавиться от скобок и / или переместить весь код в одну строку, что не может быть хорошей идеей, вы не можете.

0 голосов
/ 01 ноября 2016

В common-lisp есть функция mapcar (это не имеет никакого отношения к приведенному выше примеру с машиной). Общая функция mapcar в 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());
}

Для автомобиля-пример:

List<String> carNames = mapcar(cars, car -> car.getName());
0 голосов
/ 31 мая 2013

Если вы застряли и по-прежнему используете Apache Commons, класс Transformer может помочь: http://apachecommonstipsandtricks.blogspot.de/2009/01/examples-of-functors-transformers.html

...