У меня есть класс
public class Person {
private String name;
private String country;
private String city;
private String pet;
private int totalCountryToCityCount;
private int petCount;
public Person(String name, String country, String city, String pet, int total, int petCount) {
this.name = name;
this.country = country;
this.city = city;
this.pet = pet;
this.totalCountryToCityCount = total;
this.petCount = petCount;
}
public String getName() {
return name;
}
public String getCountry() {
return country;
}
public String getCity() {
return city;
}
public String getPet() {
return pet;
}
public int getPetCount() {
return petCount;
}
public int getTotalCountryToCityCount() {
return totalCountryToCityCount;
}
}
, и, учитывая список класса Person, я выполняю агрегации на основе различных свойств класса.Например, -
Person person1 = new Person("John", "USA", "NYC", "Max", 1, 2);
Person person2 = new Person("Steve", "UK", "London", "Lucy", 2, 8);
Person person3 = new Person("Anna", "USA", "NYC", "Max", 4, 32);
Person person4 = new Person("Mike", "USA", "Chicago", "Duke", 5, 1);
Person person5 = new Person("Test", "INDIA", "HYD", "Tommy", 4, 32);
Person person6 = new Person("Test1", "INDIA", "HYD", "Tommy", 4, 65);
Person person7 = new Person("Tim", "USA", "Chicago", "Duke", 5, 111);
Person person8 = new Person("Tim", "USA", "Chicago", "Puke", 5, 111);
Person person9 = new Person("Test1", "INDIA", "DELHI", "Tommy", 4, 65);
List<Person> persons = Arrays
.asList(person1, person2, person3, person4, person5, person6, person7, person8,
person9);
Теперь мне нужно получить результат, такой, что я должен получить итоговое значение "totalCountryToCityCount" на основе комбинаций страны и города, а мне нужно получить общее значение "petCount" на основе комбинаций страны, город и пэт.Я могу получить их отдельно, используя groupingBy и summingint
private Map<String, Map<String, Integer>> getTotalCountForCountry(List<Person> persons) {
return persons.stream().collect(groupingBy(Person::getCountry, getCityCount()));
}
public Collector<Person, ?, Map<String, Integer>> getCityCount() {
return groupingBy(Person::getCity, summingInt(Person::getTotal));
}
public Map<String, Map<String, Map<String, Integer>>> threeLevelGrouping(List<Person> persons) {
return persons
.stream().collect(
groupingBy(Person::getCountry, groupByCityAndPetName()
)
);
}
private Collector<Person, ?, Map<String, Map<String, Integer>>> groupByCityAndPetName() {
return groupingBy(Person::getCity, groupByPetName());
}
private Collector<Person, ?, Map<String, Integer>> groupByPetName() {
return groupingBy(Person::getPet, summingInt(Person::getPetCount));
}
, что дает результат
{USA={Chicago={Puke=111, Duke=112}, NYC={Max=34}}, UK={London={Lucy=8}}, INDIA={DELHI={Tommy=65}, HYD={Tommy=97}}}
{USA={Chicago=15, NYC=5}, UK={London=2}, INDIA={DELHI=4, HYD=8}}
, но фактический результат, который я хочу: -
{USA={Chicago={15,{Puke=111, Duke=112}}, NYC={5,{Max=34} }, UK={London={2, {Lucy=8}}, INDIA={DELHI={4, {Tommy=65}}, , HYD={8,{Tommy=97}}}}
есть ли способ добиться того же с помощью API потоков Java
Я также пытался использовать код -
personList.stream().collect(groupingBy(person -> person.getCountry(), collectingAndThen(reducing(
(a, b) -> new Person(a.getName(), a.getCountry(), a.getCity(), a.getPet(),
a.getTotal() + b.getTotal(), a.getPetCount() + b.getPetCount())),
Optional::get)))
.forEach((country, person) -> System.out.println(country + person));
Но получал результат -
USAPerson{name='John', country='USA', city='NYC'}
UKPerson{name='Steve', country='UK', city='London'}
INDIAPerson{name='Test', country='INDIA', city='HYD'}
с удивительным счетом