[英]split List of values based on value
我有一個對象列表(在這種情況下為Person),我想根據值將它們分成一個列表Person對象。 在下面給出的示例中,我有一個帶有名稱,id和地址對象的Person對象。 地址對象具有門牌號碼,街道ID。 現在,我想使用集合API根據地址對象中的街道ID拆分它們。 我嘗試按分組,在集合中進行分區,但無法正常工作。 我只想使用Java8。沒有第三方。
預期結果 :
[ [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 + '}';
}
}
}
應該這樣做:
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() ) ) );
為此,您需要
Stream
, groupBy
該id
的的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()
更改為
public static List<Person> test1() {
...;
return persons;
}
返回列表
滿足您需求的解決方案是使用stream().collect()
,並將person.address.streetId
字段上的groupingBy
調用作為鍵。
此代碼應執行以下操作:
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.