如何对 Stream 的元素进行分组,以便根据其属性选择单个元素
How to group element of the Stream in order to pick a single element based on its poperties
使用 Java 8 个流,我想找到一个 演员 在 一年 中出演最多电影的人].
电影列表:
List<Movie> movies= [
Movie{name="The Avengers",year="2011",actorList=["Tom","Chris","Robert"]},
Movie{name="Sherlock Holmes",year="2011",actorList=["Robert","Harris","Murphy"]},
Movie{name="Spiderman",year="2002",actorList=["Tobey","William","Kirsten"]},
...
]
电影宝珠:
class Movie{
String name;
String year;
List<String> actorList;
}
预期输出:
[年, 演员(一年内出演的电影数量上限 ), 计数(最多电影)]
["2011", "Robert", 2 ]
为此,您可以按 年份 和 演员姓名 对 电影 进行分组创建嵌套地图。然后处理它的条目。
可以用Collectors.groupingBy()
来完成。您需要将提取 年 的函数 (Movie::getYear
) 作为第一个参数传递,这将是地图的键。
作为 groupingBy
的下游收集器,您需要应用 flatMapping
从 电影对象 [=76] 中提取 演员 =].请注意,flatMapping
expect 作为参数的函数采用流元素(电影对象)和returns一个Stream
(的演员的名字).
然后是 flatMapping
的下游收集器,您需要再次应用 groupingBy
以创建一个嵌套地图,该地图将按 演员 对电影进行分组。由于只需要一些电影,counting()
必须用作下游收集器,以将映射到每个演员的 电影对象 减少到这些对象的数量。
然后将创建一个 Map<String, Map<String, Long>>
类型的中间映射,表示 actor 的电影总数 count每年.
下一步是在 条目集 上创建一个流并 展平 嵌套映射(count of movies by actor) 通过用一个新的 组合条目 包装地图中的每个条目 Map.Entry<String, Map.Entry<String, Long>>
类型,其中将包含 year、演员姓名和计数。
最后一步是找到条目,其中最大计数。
对于该操作max()
必须应用于流。它期望 Comparator
和 returns 由 Optional
包裹的结果。我假设 resume 应该存在,因此下面的代码是一个 fail-fast 实现,如果流源为空( 找不到结果,它将引发 NuSuchElementExeption
).
Comparator
是使用静态方法comparingLong()
定义的。它将根据 count 部电影生成比较器。
public static void main(String[] args) {
List<Movie> movies =
List.of(new Movie("The Avengers", "2011", List.of("Tom","Chris","Robert")),
new Movie("Sherlock Holmes", "2011", List.of("Robert","Harris","Murphy")),
new Movie("Spiderman", "2002", List.of("Tobey","William","Kirsten")));
Map.Entry<String, Map.Entry<String, Long>> result =
movies.stream()
.collect(Collectors.groupingBy(Movie::getYear,
Collectors.flatMapping(movie -> movie.getActorList().stream(),
Collectors.groupingBy(Function.identity(),
Collectors.counting()))))
.entrySet().stream()
.flatMap(entryYear -> entryYear.getValue().entrySet().stream()
.map(entryActor -> Map.entry(entryYear.getKey(),
Map.entry(entryActor.getKey(),
entryActor.getValue()))))
.max(Comparator.comparingLong(entry -> entry.getValue().getValue()))
.orElseThrow(); // NoSuchElementExeption will be thrown is the result wasn't found (if stream is empty)
System.out.println(result);
}
输出
2011=Robert=2
使用 Java 8 个流,我想找到一个 演员 在 一年 中出演最多电影的人].
电影列表:
List<Movie> movies= [
Movie{name="The Avengers",year="2011",actorList=["Tom","Chris","Robert"]},
Movie{name="Sherlock Holmes",year="2011",actorList=["Robert","Harris","Murphy"]},
Movie{name="Spiderman",year="2002",actorList=["Tobey","William","Kirsten"]},
...
]
电影宝珠:
class Movie{
String name;
String year;
List<String> actorList;
}
预期输出:
[年, 演员(一年内出演的电影数量上限 ), 计数(最多电影)]
["2011", "Robert", 2 ]
为此,您可以按 年份 和 演员姓名 对 电影 进行分组创建嵌套地图。然后处理它的条目。
可以用Collectors.groupingBy()
来完成。您需要将提取 年 的函数 (Movie::getYear
) 作为第一个参数传递,这将是地图的键。
作为 groupingBy
的下游收集器,您需要应用 flatMapping
从 电影对象 [=76] 中提取 演员 =].请注意,flatMapping
expect 作为参数的函数采用流元素(电影对象)和returns一个Stream
(的演员的名字).
然后是 flatMapping
的下游收集器,您需要再次应用 groupingBy
以创建一个嵌套地图,该地图将按 演员 对电影进行分组。由于只需要一些电影,counting()
必须用作下游收集器,以将映射到每个演员的 电影对象 减少到这些对象的数量。
然后将创建一个 Map<String, Map<String, Long>>
类型的中间映射,表示 actor 的电影总数 count每年.
下一步是在 条目集 上创建一个流并 展平 嵌套映射(count of movies by actor) 通过用一个新的 组合条目 包装地图中的每个条目 Map.Entry<String, Map.Entry<String, Long>>
类型,其中将包含 year、演员姓名和计数。
最后一步是找到条目,其中最大计数。
对于该操作max()
必须应用于流。它期望 Comparator
和 returns 由 Optional
包裹的结果。我假设 resume 应该存在,因此下面的代码是一个 fail-fast 实现,如果流源为空( 找不到结果,它将引发 NuSuchElementExeption
).
Comparator
是使用静态方法comparingLong()
定义的。它将根据 count 部电影生成比较器。
public static void main(String[] args) {
List<Movie> movies =
List.of(new Movie("The Avengers", "2011", List.of("Tom","Chris","Robert")),
new Movie("Sherlock Holmes", "2011", List.of("Robert","Harris","Murphy")),
new Movie("Spiderman", "2002", List.of("Tobey","William","Kirsten")));
Map.Entry<String, Map.Entry<String, Long>> result =
movies.stream()
.collect(Collectors.groupingBy(Movie::getYear,
Collectors.flatMapping(movie -> movie.getActorList().stream(),
Collectors.groupingBy(Function.identity(),
Collectors.counting()))))
.entrySet().stream()
.flatMap(entryYear -> entryYear.getValue().entrySet().stream()
.map(entryActor -> Map.entry(entryYear.getKey(),
Map.entry(entryActor.getKey(),
entryActor.getValue()))))
.max(Comparator.comparingLong(entry -> entry.getValue().getValue()))
.orElseThrow(); // NoSuchElementExeption will be thrown is the result wasn't found (if stream is empty)
System.out.println(result);
}
输出
2011=Robert=2