Java 8个收集器groupBy并分成一个单独的class
Java 8 collectors groupBy and into a separate class
我有一个 Persons
的列表,其中有一些重名。
class Person {
String name;
}
我想将其转换为 GroupedPersons
的列表,其中包含通用名称和所有具有该名称的人的列表。
class GroupedPerson {
String name;
List<A> as;
}
是否可以使用一个收集器来完成此操作,而无需任何中间映射或额外的 类?
我想一种方法是:
persons
.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(
Person::getName),
map -> {
return map.entrySet()
.stream()
.map(en -> new GroupedPerson(en.getKey(), en.getValue()))
.collect(Collectors.toList());
}));
或者,您可以使用 toMap
:
persons
.stream()
.collect(Collectors.toMap(
Person::getName,
x -> {
List<Person> l = new ArrayList<>();
l.add(x);
return new GroupedPerson(x.getName(), l);
},
(left, right) -> {
left.getAs().addAll(right.getAs());
return left;
}))
.values();
是的,你可以做到。这是一种方法:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class GroupedStream {
public static void main(String[] args) {
List<GroupedPerson> groupedPersons = Arrays.asList("john harry john harry sam jordon bill steve bill".split(" "))
.stream()
.map(name -> new Person(name))
.map(person -> new Object[] {person.name, new ArrayList<>()})
.collect(Collectors.toMap(tuple-> (String) tuple[0], tuple -> (List<Person>) tuple[1] ))
.entrySet()
.stream()
.map(entry -> new GroupedPerson(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
static class Person {
public final String name;
public Person(String name) {
super();
this.name = name;
}
}
static class GroupedPerson {
public final String name;
public final List<Person> person;
public GroupedPerson(String name, List<Person> person) {
this.name = name;
this.person = person;
}
}
}
如果您将 GroupedPerson
模型修改为以下内容:
public class GroupedPerson {
private String name;
private List<Person> people;
public GroupedPerson(String name) {
this.name = name;
people = new ArrayList<>();
}
public void addPeople(List<Person> people) {
this.people.addAll(people);
}
public void addPerson(Person person){
people.add(person);
}
public List<Person> getPeople(){
return Collections.unmodifiableList(people);
}
public String getName() {
return name;
}
}
然后你可以有一个 Collection
个 GroupedPerson
个对象,其中包含名称和所有具有该特定名称的相应人员,如下所示:
Collection<GroupedPerson> resultSet = peopleList
.stream()
.collect(Collectors.toMap(Person::getName,
p -> {
GroupedPerson groupedPerson = new GroupedPerson(p.getName());
groupedPerson.addPerson(p);
return groupedPerson;
},
(p, p1) -> {
p.addPeople(p1.getPeople());
return p;
}
)).values();
如果出于某种原因您不希望接收器类型为 Collection<T>
那么您可以转换为特定的集合类型(如果认为合适的话,只需简单地执行即可)。
List<GroupedPerson> result = new ArrayList<>(resultSet);
我有一个 Persons
的列表,其中有一些重名。
class Person {
String name;
}
我想将其转换为 GroupedPersons
的列表,其中包含通用名称和所有具有该名称的人的列表。
class GroupedPerson {
String name;
List<A> as;
}
是否可以使用一个收集器来完成此操作,而无需任何中间映射或额外的 类?
我想一种方法是:
persons
.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(
Person::getName),
map -> {
return map.entrySet()
.stream()
.map(en -> new GroupedPerson(en.getKey(), en.getValue()))
.collect(Collectors.toList());
}));
或者,您可以使用 toMap
:
persons
.stream()
.collect(Collectors.toMap(
Person::getName,
x -> {
List<Person> l = new ArrayList<>();
l.add(x);
return new GroupedPerson(x.getName(), l);
},
(left, right) -> {
left.getAs().addAll(right.getAs());
return left;
}))
.values();
是的,你可以做到。这是一种方法:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class GroupedStream {
public static void main(String[] args) {
List<GroupedPerson> groupedPersons = Arrays.asList("john harry john harry sam jordon bill steve bill".split(" "))
.stream()
.map(name -> new Person(name))
.map(person -> new Object[] {person.name, new ArrayList<>()})
.collect(Collectors.toMap(tuple-> (String) tuple[0], tuple -> (List<Person>) tuple[1] ))
.entrySet()
.stream()
.map(entry -> new GroupedPerson(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
static class Person {
public final String name;
public Person(String name) {
super();
this.name = name;
}
}
static class GroupedPerson {
public final String name;
public final List<Person> person;
public GroupedPerson(String name, List<Person> person) {
this.name = name;
this.person = person;
}
}
}
如果您将 GroupedPerson
模型修改为以下内容:
public class GroupedPerson {
private String name;
private List<Person> people;
public GroupedPerson(String name) {
this.name = name;
people = new ArrayList<>();
}
public void addPeople(List<Person> people) {
this.people.addAll(people);
}
public void addPerson(Person person){
people.add(person);
}
public List<Person> getPeople(){
return Collections.unmodifiableList(people);
}
public String getName() {
return name;
}
}
然后你可以有一个 Collection
个 GroupedPerson
个对象,其中包含名称和所有具有该特定名称的相应人员,如下所示:
Collection<GroupedPerson> resultSet = peopleList
.stream()
.collect(Collectors.toMap(Person::getName,
p -> {
GroupedPerson groupedPerson = new GroupedPerson(p.getName());
groupedPerson.addPerson(p);
return groupedPerson;
},
(p, p1) -> {
p.addPeople(p1.getPeople());
return p;
}
)).values();
如果出于某种原因您不希望接收器类型为 Collection<T>
那么您可以转换为特定的集合类型(如果认为合适的话,只需简单地执行即可)。
List<GroupedPerson> result = new ArrayList<>(resultSet);