我正在尝试使用Java 8 Stream API,并希望使用Java 8流过滤器map reduce转换以下方法。
我有一个电影列表,每个电影对象都有一个演员列表以及其他字段。
我想查找所有具有特定名字和姓氏的演员都曾参与过的电影。
下面的方法基于Java 7,其中我遍历电影列表,然后遍历该电影的演员列表。如果找到具有名字和姓氏的演员,我将中断内部循环并将该电影添加到返回的电影列表中。
注释的代码有效,我可以获取正确的电影列表。
我的问题是如何使用Java 8流重新编写此代码。我可以看到这是一个地图,过滤器,减少问题,但我无法提出明确的解决方案。
public List<Movie> getMoviesForActor(String firstName, String lastName) {
final List<Movie> allMovies = movieRepository.getAllMovies();
final Predicate<Actor> firstNamePredicate = actor -> actor.getFirstName().equalsIgnoreCase(firstName);
final Predicate<Actor> lastNamePredicate = actor -> actor.getLastName().equalsIgnoreCase(lastName);
final List<Movie> movies = new ArrayList<>();
// for (Movie movie : allMovies) {
// boolean actorFound = false;
// for (Actor actor : movie.getActors()) {
// if(firstName.equalsIgnoreCase(actor.getFirstName()) && lastName.equalsIgnoreCase(actor.getLastName())) {
// actorFound = true;
// break;
// }
// }
// if(actorFound) {
// movies.add(movie);
// }
// }
final List<Actor> actors = allMovies.stream()
.flatMap(
movie -> movie.getActors().stream().filter(firstNamePredicate.and(lastNamePredicate))
).collect(Collectors.toList());
return movies;
}
如果我在电影上进行流媒体播放并将其平面映射,并在其中播放演员列表,那么在只有该名字和姓氏的演员存在的情况下,如何才能再次获得电影列表?
答案 0 :(得分:3)
由于其他答案已经解决了java-8
中解决问题的方式,因此,使用此解决方案,您可以使用java-9
中引入的所有全新Collectors.filtering
。因此,只需将其留在此处即可供将来参考。
List<Movie> movies = allMovies.stream()
.collect(Collectors.filtering(
m -> m.getActors().stream().anyMatch(firstNamePredicate.and(lastNamePredicate)),
Collectors.toList()));
答案 1 :(得分:2)
使用Java8中的anyMatch
短路终端操作,可以轻松地找到第一个匹配元素,同时循环遍历可迭代的对象,一旦找到它就可以中断。然后将anyMatch
的结果传递给filter
运算符,以获取符合给定条件的所有电影。
我宁愿建议您使用内联谓词,而不要单独定义它们,除非您在其他地方重用它们。这样会导致代码更加简洁,而冗长程度降低。这是它的外观。
movies.stream()
.filter(m -> m.getActors().stream()
.anyMatch(
a -> a.getFirstName().equalsIgnoreCase(firstName)
&& a.getLastName().equalsIgnoreCase(lastName)))
.collect(Collectors.toList());
由于某些原因,如果您确实需要使用问题陈述中给出的预定义谓词,则可以这样做,
movies.stream()
.filter(m -> m.getActors().stream()
.anyMatch(firstNamePredicate.and(lastNamePredicate)))
.collect(Collectors.toList());
答案 2 :(得分:2)
用现有代码编写它的更好的方法(功能)是:
this.someService.login().subscribe(res => {
localStorage.setItem('token', res.data.token); // <-- add these lines
localStorage.setItem('id', res.data.id); // <--
});
答案 3 :(得分:1)
还有一个解决方案。
有时使用错误的收集类型会使您的生活变得困难。我建议Movie.getActors()
返回一个Set<Actor>
而不是一个List<Actor>
。这将使处理变得容易得多。
private class Movie {
public Set<Actor> getActors() {
return null;
}
}
private class Actor {
private final String firstName;
private final String lastName;
private Actor(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Actor)) return false;
Actor actor = (Actor) o;
return firstName.equals(actor.firstName) &&
lastName.equals(actor.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
}
final List<Movie> allMovies = Collections.EMPTY_LIST;
public List<Movie> getMoviesForActor(String firstName, String lastName) {
Actor actor = new Actor(firstName, lastName);
return allMovies.stream()
.filter(m -> m.getActors().contains(actor))
.collect(Collectors.toList());
}