Java stream/collect: map one item with multiple fields to multiple keys(Java 流/收集:将具有多个字段的一项映射到多个键)
问题描述
我想尝试使用 java 收集器编写以下代码.
I have the following code that I'd like to try to write using the java collectors.
给定一个人的 2 个属性(名字和姓氏),我想获得一张地图,其中包含唯一的名字或姓氏作为键,以及相应人员的列表.
Given 2 attributes (firstname and lastname) of a person, I'd like to get a map containing the unique firstname or lastname as a key, and the list of the corresponding persons.
这是一组数据:
Person person1 = new Person();
person1.setFirstName("john");
person1.setLastName("doe");
person1.setUserId("user1");
Person person2 = new Person();
person2.setFirstName("doe");
person2.setLastName("frank");
person2.setUserId("user2");
Person person3 = new Person();
person3.setFirstName("john");
person3.setLastName("wayne");
person3.setUserId("user3");
List<Person> personList = new ArrayList<>();
personList.add(person1);
personList.add(person2);
personList.add(person3);
输出(如预期)如下:
frank=[Person{userId='user2', firstName='doe', lastName='frank'}],
john=[Person{userId='user1', firstName='john', lastName='doe'}, Person{userId='user3', firstName='john', lastName='wayne'}],
doe=[Person{userId='user1', firstName='john', lastName='doe'}, Person{userId='user2', firstName='doe', lastName='frank'}],
wayne=[Person{userId='user3', firstName='john', lastName='wayne'}]
以及填充地图的代码:
Map<String, List<Person>> mapPersons = new HashMap<String, List<Person>>();
List<Person> listPersons;
for (Person p: personList) {
if (mapPersons.get(p.getFirstName()) == null) {
listPersons = new ArrayList<Person>();
listPersons.add(p);
mapPersons.put(p.getFirstName(), listPersons);
} else {
mapPersons.get(p.getFirstName()).add(p);
}
if (mapPersons.get(p.getLastName()) == null) {
listPersons = new ArrayList<Person>();
listPersons.add(p);
mapPersons.put(p.getLastName(), listPersons);
} else {
mapPersons.get(p.getLastName()).add(p);
}
}
我不知道如何将名字或姓氏作为键(不像 在java 8中按多个字段名分组).我必须自己写收集器吗?
I can't figure out how I can get either the firstname or the lastname as a key (not like in Group by multiple field names in java 8). Do I have to write my own collector?
推荐答案
您可以将 Stream.flatMap()
和 Collectors.groupingBy()
与 Collectors 一起使用.mapping()
:
You can use Stream.flatMap()
and Collectors.groupingBy()
with Collectors.mapping()
:
Map<String, List<Person>> result = personList.stream()
.flatMap(p -> Stream.of(p.getFirstName(), p.getLastName()).map(n -> new AbstractMap.SimpleEntry<>(n, p)))
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
这使用 flatMap
将所有名称(名字和姓氏)扩展为它们的 Person
对象,然后收集它.
This uses flatMap
to expand all names (first and last) to their Person
object and collects it afterwards.
或者使用 Java 9 或更高版本,您可以使用 Collectors.flatMapping()
:
Alternatively using Java 9 or above you could use Collectors.flatMapping()
:
Map<String, List<Person>> result = personList.stream()
.collect(Collectors.flatMapping(
p -> Stream.of(p.getFirstName(), p.getLastName()).map(n -> new AbstractMap.SimpleEntry<>(n, p)),
Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.toList()))));
但我不认为这更具可读性.
But I don't think that this is more readable.
这篇关于Java 流/收集:将具有多个字段的一项映射到多个键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Java 流/收集:将具有多个字段的一项映射到多个键
基础教程推荐
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 在螺旋中写一个字符串 2022-01-01