我试图在Java 8中理解Lambdas。
假设我有一个类似于此的Person类:
public class Person implements {
String name;
GenderEnum gender;
int age;
List<Person> children;
}
现在我要做的是找到所有女性,有10岁以下孩子的人。
Pre java 8我会这样做:
List<Person> allPersons = somePeople();
List<Person> allFemaleWithChildren = new ArrayList<>();
for(Person p : allPersons) {
for(Person child : p.getChildren()) {
if(child.getAge() < 10 && p.getGender() == GenderEnum.Female) {
allFemaleWithChildren.add(p);
}
}
}
现在allFemaleWithChildren应该拥有我想要的东西。 我一直试图使用流做同样的事情 我想我需要使用某种地图,过滤和减少
allPersons.stream()
//filter females
.filter(p -> p.getGender == GenderEnum.Female)
//get the children
.map(c -> c.getChildren())
//filter the ones that are less than 10 years
.filter(c -> c.getAge() < 10)
//return a list with the result
.collect(Collectors.toList())
但是这段代码没有编译。 我错过了什么。
另外,我不明白可以使用reduce方法。
编译器说
cannot resolve method getAge()
。这是因为c
显然是一个集合,而不是集合中的项目,这正是我想要的。
答案 0 :(得分:9)
此刻(一旦你修复了编译错误),你将返回一个Children列表。假设在您的原始代码中,一旦您找到10岁以下的孩子,您打算打破,相当于以下内容:
allPersons.stream()
//filter females
.filter(p -> p.getGender() == GenderEnum.Female)
//only keep females with at least one child < 10
.filter(f -> f.getChildren().stream()
.anyMatch(c -> c.getAge() < 10))
//return a list with the result
.collect(Collectors.toList())
确实如下所述,您可以使用一些静态导入,添加辅助方法并重构原始代码以使其更具可读性:
allPersons.stream()
.filter(this::female)
.filter(this::hasChildrenUnder10)
.collect(toList())
//...
private boolean female(Person p) { return p.getGender() == Female; }
private boolean hasChildrenUnder10(Person parent) {
return parent.getChildren().stream()
.anyMatch(c -> c.getAge() < 10));
}
答案 1 :(得分:1)
你有2个for
循环,这意味着在某些时候你需要另一个流。在您致电map
时,您可以将您的母亲映射到儿童名单。然后,你继续进行,好像你有一群孩子,但实际上你有一群孩子的集合。