我有一个对象列表(本例中为Person),我想根据值将它们拆分为一个列表Person对象列表。在下面给出的示例中,我有一个Person对象,其中包含name,id和Address对象。地址对象有一个门牌号码,街道ID。现在我想使用集合API在地址对象中基于Street Id拆分它们。我尝试分组,在集合中进行分区,但无法使其正常工作。我只想使用Java 8.没有第三方。
预期结果:
[ [person1, person2, person3] , [person4, person5], [person6] ]
感谢。
package testapplication2;
import java.util.ArrayList;
import java.util.List;
/**
*
*
*/
public class JavaCollections {
public static void main(String[] args) {
JavaCollections c = new JavaCollections();
c.test1();
}
public void test1() {
List<Person> persons = new ArrayList<>();
Address address1 = new Address(1, "X Street", 100);
Address address2 = new Address(2, "X Street", 100);
Address address3 = new Address(3, "X Street", 100);
Address address4 = new Address(4, "Y Street", 101);
Address address5 = new Address(5, "Y Street", 101);
Address address6 = new Address(6, "Z Street", 102);
persons.add(new Person(1, "P1", address1));
persons.add(new Person(2, "P2", address2));
persons.add(new Person(3, "P3", address3));
persons.add(new Person(4, "P4", address4));
persons.add(new Person(5, "P5", address5));
persons.add(new Person(6, "P6", address6));
}
public class Person {
public int personId;
private String name;
private Address address;
public Person() {
}
public Person(int personId, String name, Address address) {
super();
this.personId = personId;
this.name = name;
this.address = address;
}
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" + "personId=" + personId + ", name=" + name + ", address=" + address + '}';
}
}
public class Address {
public Address() {
}
public Address(int houseNumber, String streetName, int streetId) {
this.houseNumber = houseNumber;
this.streetId = streetId;
this.streetName = streetName;
}
private int houseNumber;
private String streetName;
private int streetId;
public int getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(int houseNumber) {
this.houseNumber = houseNumber;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public int getStreetId() {
return streetId;
}
public void setStreetId(int streetId) {
this.streetId = streetId;
}
@Override
public String toString() {
return "Address{" + "houseNumber=" + houseNumber + ", streetName=" + streetName + ", streetId=" + streetId + '}';
}
}
}
答案 0 :(得分:2)
这应该这样做:
List< List<Person> > groups = new ArrayList<>( persons.stream().collect(
Collectors.groupingBy( p -> p.getAddress().getStreetId() ) ).values() );
或者@shmosel:
List< List<Person> > groups = persons.stream().collect( Collectors.collectingAndThen(
Collectors.groupingBy( p -> p.getAddress().getStreetId() ),
m -> new ArrayList<>( m.values() ) ) );
答案 1 :(得分:1)
要实现这一目标,您需要
Stream
groupBy
id
的{{1}},具有相同Address
的所有人将在一起adressId
Map<Integer,List<Person>>
(所有values
并将它们聚集在一起)List<Person>
将public static void main(String[] args) {
JavaCollections c = new JavaCollections();
List<Person> persons = c.test1();
List<List<Person>> res = new ArrayList<>(persons .stream()
.collect(Collectors.groupingBy(o -> o.getAddress().getStreetId())).values());
System.out.println(test);
}
更改为
test1()
返回列表
答案 2 :(得分:1)
您的要求的解决方案是stream().collect()
在groupingBy
字段上使用person.address.streetId
作为密钥使用{/ p}。
此代码应该这样做:
final List<List<Person>> groupedPersons = persons.stream()
.collect(Collectors.groupingBy(o -> o.address.streetId))
.entrySet().stream()
.map(Map.Entry::getValue).collect(Collectors.toList());
// Code for printing out
groupedPersons.forEach(people -> {
System.out.print("[");
System.out.print(people.stream().map(person -> String.format("person%d", person.personId)).collect(Collectors.joining(",")));
System.out.print("]");
});
以下是您可以运行的完整示例:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Partitions {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
Address address1 = new Address(1, "X Street", 100);
Address address2 = new Address(2, "X Street", 100);
Address address3 = new Address(3, "X Street", 100);
Address address4 = new Address(4, "Y Street", 101);
Address address5 = new Address(5, "Y Street", 101);
Address address6 = new Address(6, "Z Street", 102);
persons.add(new Person(1, "P1", address1));
persons.add(new Person(2, "P2", address2));
persons.add(new Person(3, "P3", address3));
persons.add(new Person(4, "P4", address4));
persons.add(new Person(5, "P5", address5));
persons.add(new Person(6, "P6", address6));
final List<List<Person>> groupedPersons = persons.stream()
.collect(Collectors.groupingBy(o -> o.address.streetName))
.entrySet().stream()
.map(Map.Entry::getValue).collect(Collectors.toList());
groupedPersons.forEach(people -> {
System.out.print("[");
System.out.print(people.stream().map(person -> String.format("person%d", person.personId)).collect(Collectors.joining(",")));
System.out.print("]");
});
}
public static class Person {
public int personId;
private String name;
private Address address;
public Person() {
}
public Person(int personId, String name, Address address) {
super();
this.personId = personId;
this.name = name;
this.address = address;
}
public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" + "personId=" + personId + ", name=" + name + ", address=" + address + '}';
}
}
public static class Address {
private int houseNumber;
private String streetName;
private int streetId;
public Address() {
}
public Address(int houseNumber, String streetName, int streetId) {
this.houseNumber = houseNumber;
this.streetId = streetId;
this.streetName = streetName;
}
public int getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(int houseNumber) {
this.houseNumber = houseNumber;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public int getStreetId() {
return streetId;
}
public void setStreetId(int streetId) {
this.streetId = streetId;
}
@Override
public String toString() {
return "Address{" + "houseNumber=" + houseNumber + ", streetName=" + streetName + ", streetId=" + streetId + '}';
}
}
}
这将打印出来:
[person4,person5][person6][person1,person2,person3]
<强>更新强>
如果要保留添加到初始列表的顺序,可以提供一个提供java.util.LinkedHashSet
的收集器 - 一种保留唯一性和原始插入顺序的数据结构。
分组代码如下所示:
final List<Set<Person>> groupedPersons = persons.stream()
.collect(Collectors.groupingBy(o -> o.address.streetId,
Collector.of(() -> new LinkedHashSet<Person>(), HashSet::add, (s1, s2) -> {
s1.addAll(s2);
return s1;
})))
.entrySet().stream()
.map(Map.Entry::getValue).collect(Collectors.toList());
如果您在上面的示例中使用此代码,则会打印出来:
[person1,person2,person3][person4,person5][person6]