假设我有一个类
Class Person {
String name;
String uid;
String phone;
}我正试着按全班的所有字段分组。如何使用JAVA 8中的并行流来转换
List<Person> into Map<String,Set<Person>>其中,映射的键是类中每个字段的值。以下示例按单个字段分组,如何将类的所有字段组合成单个Map?
ConcurrentMap<Person.Sex, List<Person>> byGender =
roster
.parallelStream()
.collect(
Collectors.groupingByConcurrent(Person::getGender));发布于 2017-12-16 18:46:02
您可以通过使用来自of的Collector的静态工厂方法来实现这一点。
Map<String, Set<Person>> groupBy = persons.parallelStream()
.collect(Collector.of(
ConcurrentHashMap::new,
( map, person ) -> {
map.computeIfAbsent(person.name, k -> new HashSet<>()).add(person);
map.computeIfAbsent(person.uid, k -> new HashSet<>()).add(person);
map.computeIfAbsent(person.phone, k -> new HashSet<>()).add(person);
},
( a, b ) -> {
b.forEach(( key, set ) -> a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
return a;
}
));正如霍尔格在评论中所建议的那样,以下方法比上面的方法更可取:
Map<String, Set<Person>> groupBy = persons.parallelStream()
.collect(HashMap::new, (m, p) -> {
m.computeIfAbsent(p.name, k -> new HashSet<>()).add(p);
m.computeIfAbsent(p.uid, k -> new HashSet<>()).add(p);
m.computeIfAbsent(p.phone, k -> new HashSet<>()).add(p);
}, (a, b) -> b.forEach((key, set) -> {
a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
});它使用重载的collect方法,它的行为与我上面建议的语句相同。
发布于 2017-12-16 18:29:33
您可以连锁您的分组收集器,这将给您一个多层次的地图。但是,如果您想按两个以上的字段进行分组,这是不理想的。
更好的选择是覆盖equals和hashcode类中的Person方法,以定义两个给定对象的相等,在本例中,这些对象就是所有上述字段。然后您可以按Person i.e groupingByConcurrent(Function.identity())进行分组,在这种情况下,您将得到以下结果:
ConcurrentMap<Person, List<Person>> resultSet = ....示例:
class Person {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (name != null ? !name.equals(person.name) : person.name != null) return false;
if (uid != null ? !uid.equals(person.uid) : person.uid != null) return false;
return phone != null ? phone.equals(person.phone) : person.phone == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (uid != null ? uid.hashCode() : 0);
result = 31 * result + (phone != null ? phone.hashCode() : 0);
return result;
}
private String name;
private String uid; // these should be private, don't expose
private String phone;
// getters where necessary
// setters where necessary
}然后:
ConcurrentMap<Person, List<Person>> resultSet = list.parallelStream()
.collect(Collectors.groupingByConcurrent(Function.identity()));https://stackoverflow.com/questions/47848696
复制相似问题