假设我有一个汽车列表:
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]
答案 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 references(oracle 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
,但这不会发生。
尽管这是他们“惰性视图”方法的结果,但仍然非常令人惊讶。