通过生成映射到其集合值中元素计数的每个键的新映射来报告多图
Report on a multimap by producing a new map of each key mapped to the count of elements in its collection value
想象一个 multimap 跟踪人员,每个人都有一个分配任务列表。
Map< Person , List< Task > > personToTasks =
Map.of(
new Person( "Alice" ) , List.of( new Task( "a1" ), new Task( "a2") ) ,
new Person( "Bob" ) , List.of( new Task( "b1" ) ) ,
new Person( "Carol" ) , List.of( new Task( "c1" ), new Task( "c2"), new Task( "c3") )
)
;
我如何使用流获取新地图,将每个 Person
映射到一个 Integer
,其中包含在分配任务列表中找到的项目数?
如何获得与此硬编码地图等效的结果:
Map< Person , Integer > personToTaskCount =
Map.of(
new Person( "Alice" ) , 2 ,
new Person( "Bob" ) , 1 ,
new Person( "Carol" ) , 3
)
;
我一直在尝试排列:
Map < Person, Integer > personToTaskCount =
personToTasks.keySet().stream().collect
(
Collectors.mapping
(
Map.Entry :: getKey ,
???
)
)
;
您走在正确的轨道上,这是一个可能的解决方案:
Map<Person, Integer> personToTaskCount = personToTasks
.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().size()));
Map#entrySet
method returns a Set
of the elements in a map, a set of Map.Entry
个对象。 Map.Entry
保存映射中每个条目的键值对。我们可以向该对象询问键和值。
在您的示例中,询问每个 Map.Entry
的值会得到 List< Task >
。然后我们可以询问该列表的大小,它包含的元素数量。这个大小数字是我们希望您的新地图的值,Map < Person, Integer >
。
这里是上面代码的扩展版本,使这些 Map.Entry
对象的作用更加明显。
Map < Person, List < Task > > personToTasks =
Map.of(
new Person( "Alice" ) , List.of( new Task( "a1" ) , new Task( "a2" ) ) ,
new Person( "Bob" ) , List.of( new Task( "b1" ) ) ,
new Person( "Carol" ) , List.of( new Task( "c1" ) , new Task( "c2" ) , new Task( "c3" ) )
);
Map < Person, Integer > personToTaskCount =
personToTasks
.entrySet()
.stream()
.collect(
Collectors.toMap(
( Map.Entry < Person, List < Task > > e ) -> { return e.getKey(); } ,
( Map.Entry < Person, List < Task > > e ) -> { return e.getValue().size(); }
)
);
将结果转储到控制台。
System.out.println( "personToTasks = " + personToTasks );
System.out.println( "personToTaskCount = " + personToTaskCount );
当运行.
personToTasks = {Person[name=Alice]=[Task[title=a1], Task[title=a2]], Person[name=Carol]=[Task[title=c1], Task[title=c2], Task[title=c3]], Person[name=Bob]=[Task[title=b1]]}
personToTaskCount = {Person[name=Bob]=1, Person[name=Alice]=2, Person[name=Carol]=3}
想象一个 multimap 跟踪人员,每个人都有一个分配任务列表。
Map< Person , List< Task > > personToTasks =
Map.of(
new Person( "Alice" ) , List.of( new Task( "a1" ), new Task( "a2") ) ,
new Person( "Bob" ) , List.of( new Task( "b1" ) ) ,
new Person( "Carol" ) , List.of( new Task( "c1" ), new Task( "c2"), new Task( "c3") )
)
;
我如何使用流获取新地图,将每个 Person
映射到一个 Integer
,其中包含在分配任务列表中找到的项目数?
如何获得与此硬编码地图等效的结果:
Map< Person , Integer > personToTaskCount =
Map.of(
new Person( "Alice" ) , 2 ,
new Person( "Bob" ) , 1 ,
new Person( "Carol" ) , 3
)
;
我一直在尝试排列:
Map < Person, Integer > personToTaskCount =
personToTasks.keySet().stream().collect
(
Collectors.mapping
(
Map.Entry :: getKey ,
???
)
)
;
您走在正确的轨道上,这是一个可能的解决方案:
Map<Person, Integer> personToTaskCount = personToTasks
.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().size()));
Map#entrySet
method returns a Set
of the elements in a map, a set of Map.Entry
个对象。 Map.Entry
保存映射中每个条目的键值对。我们可以向该对象询问键和值。
在您的示例中,询问每个 Map.Entry
的值会得到 List< Task >
。然后我们可以询问该列表的大小,它包含的元素数量。这个大小数字是我们希望您的新地图的值,Map < Person, Integer >
。
这里是上面代码的扩展版本,使这些 Map.Entry
对象的作用更加明显。
Map < Person, List < Task > > personToTasks =
Map.of(
new Person( "Alice" ) , List.of( new Task( "a1" ) , new Task( "a2" ) ) ,
new Person( "Bob" ) , List.of( new Task( "b1" ) ) ,
new Person( "Carol" ) , List.of( new Task( "c1" ) , new Task( "c2" ) , new Task( "c3" ) )
);
Map < Person, Integer > personToTaskCount =
personToTasks
.entrySet()
.stream()
.collect(
Collectors.toMap(
( Map.Entry < Person, List < Task > > e ) -> { return e.getKey(); } ,
( Map.Entry < Person, List < Task > > e ) -> { return e.getValue().size(); }
)
);
将结果转储到控制台。
System.out.println( "personToTasks = " + personToTasks );
System.out.println( "personToTaskCount = " + personToTaskCount );
当运行.
personToTasks = {Person[name=Alice]=[Task[title=a1], Task[title=a2]], Person[name=Carol]=[Task[title=c1], Task[title=c2], Task[title=c3]], Person[name=Bob]=[Task[title=b1]]}
personToTaskCount = {Person[name=Bob]=1, Person[name=Alice]=2, Person[name=Carol]=3}