如何在List的每个元素上调用方法?

时间:2011-08-28 15:24:02

标签: java list list-comprehension

假设我有一个汽车列表:

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

如何缩短上面的代码?简而言之,如何在List的每个元素上调用方法?

例如,在Python中:

[car.name for car in cars]

6 个答案:

答案 0 :(得分:60)

  

Java 8将(希望)具有某种形式的lambda表达式,这将使这样的代码更加可行。 (是否有类似列表推导的内容是另一回事。)

你的愿望已被授予!

--- --- EDIT
大声笑,好像在提示: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
我应该早点看到这个,但我无法抗拒,只能发布它。

jdk8中添加的Stream功能允许使用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() );

更简洁的是使用Java 8的method referencesoracle doc)。

List<String> names = cars.stream().map( Car::getName ).collect( Collectors.toList() );

答案 1 :(得分:21)

<强>更新

有关使用lambda表达式的Java 8解决方案,请参阅aaiezza的answer

原始的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 :(得分:2)

除了摆脱括号和/或将所有代码移动到一行,这可能不是一个好主意,你不能。

答案 3 :(得分:0)

如果您遇到困难并且仍然必须使用Apache Commons,那么Transformer类可以提供帮助:http://apachecommonstipsandtricks.blogspot.de/2009/01/examples-of-functors-transformers.html

答案 4 :(得分:0)

在common-lisp中有一个mapcar函数(这与上面的汽车示例无关)。 Java中的一般mapcar函数:

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

答案 5 :(得分:0)

除非您知道番石榴的用途,否则最好远离番石榴的Lists.transform。查看此代码段:

public class User {
    private Integer id;
    // constructor, getters & setters
}

public class UserDto {
    private Integer id;
    private boolean processed;

    public UserDto(User user) {
        this.id = user.getId();
        this.processed = false;
    }
   // getters & setters
}

// now let's do actual transformation ...
private List<UserDto> getUsers() {
    List<User> users = List.of(new User(1), new User(2));
    List<UserDto> userDtos = Lists.transform(users, UserDto::new);
    userDtos.forEach(userDto -> userDto.setProcessed(true));
    return userDtos;
}

您可能希望所有DTO的processed标志都设置为true,但这不会发生。 尽管这是他们“惰性视图”方法的结果,但仍然非常令人惊讶。