【发布时间】:2019-11-19 00:11:20
【问题描述】:
我想尝试使用 java 收集器编写以下代码。
给定一个人的 2 个属性(名字和姓氏),我想获得一张地图,其中包含唯一的名字或姓氏作为键,以及相应人员的列表。
这是一组数据:
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);
}
}
我不知道如何将名字或姓氏作为键(不像Group by multiple field names in java 8)。我必须自己写收集器吗?
【问题讨论】:
-
作为旁注(与您的问题无关),如果没有使用较新的方法
Map.computeIfAbsent等(docs.oracle.com/javase/8/docs/api/java/util/…) -
真的!但这是我刚刚从 java 6 应用程序中获取的旧代码!
-
由于每个项目最终都会成为两个键,
toMap和groupingBy将不起作用。我认为编写自己的收藏家是最好的方法。或者,使用名字/姓氏作为键复制每个项目(如 Samuels 的回答)也可以。 -
也应该把标题改成“将一个具有多个字段的项映射到多个键”?
-
@sfiss’ comment 很有价值,因为重写循环以使用
computeIfAbsent可能最终得到比 Stream 解决方案更简单的代码。
标签: java java-8 java-stream