У меня есть результат List в моем сервисном методе Spring Boot, как показано ниже:
Country:
String name;
List<State> states;
State:
String name;
Long population;
List<Town> towns;
Town:
String name;
Я возвращаю список стран из своего репозитория, и в нем есть все соответствующие даты штата и города для каждой страны. Я хочу сопоставить эти данные с DTO, как показано ниже:
public class CountryDTO {
private Long id;
private String name;
private Long population; //population sum of states by country
private List<Town> towns;
//constructor
}
Итак, как мне правильно сопоставить объект Country с этим CountryDTO, как описано выше? Мне нужны следующие данные:
Имя страны Сумма населения по каждой стране Города каждой страны
Обновление: вот мой метод обслуживания, в котором я пытался использовать Java Stream, а затем и ModelMapper, но не могу вернуть желаемые значения :(
List<CountryDTO> countries = countryRepository.findAll().stream()
.flatMap(x -> x.getStates().stream())
.map(x -> new CountryDTO(x.getCountry(), <-- need to return sum of population here -->, ObjectMapperUtils.mapAll(x.getTowns(), TownDTO.class)))
.toList();
Stream#mapToInt
, чтобы получить все населения штата, и .sum
, чтобы сложить их.Stream#flatMap
можно использовать, чтобы собрать все города каждого штата в один поток.List<CountryDTO> res = countries.stream().map(c -> new CountryDTO(c.getName(),
c.getStates().stream().mapToInt(State::getPopulation).sum(),
c.getStates().stream().flatMap(s -> s.getTowns().stream()).toList())).toList();
Сейчас попробую c.getStates().stream().map(State::getPopulation).reduce(BigDecimal.ZERO, BigDecimal::add),
@rosy c.getStates().stream().map(s -> new BigDecimal(s.getPopulation())).reduce(BigDecimal.ZERO, BigDecimal::add)
должна это сделать. (Вам нужно сначала преобразовать каждый Long
в BigDecimal
.)
Не совсем понял ваш вопрос, возможно, будет полезнее, если вы поделитесь точным ответом, возвращаемым API.
Но, исходя из варианта использования, если вы получаете список в ответе, у вас всегда есть возможность передать список, выполнить итерацию каждого элемента, а затем использовать логику условной/группировки для получения данных желаемым способом.
Например;
Допустим, у вас есть список типа Object
, для которого у вас есть слой репозитория, настроенный как ObjetRepo
. Теперь, если вы получаете список объектов, вы можете передать его следующим образом:
@Autowired
private ObjectRepo objectRepo;
public List<Object> method() {
List<Object> objects = new ArrayList<>();
objectRepo.findAll().forEach(objects::add);
// Here, instead of add, any other logic can be used.
// You can also write a method, and use that method here
// objectRepo.findAll().forEach(objects::someMethod);
return objects;
}
Большое спасибо за этот полезный ответ. Я пробую этот подход, но мне просто нужно суммировать
population
какBigDecimal
вместоInteger
, и я не могу использоватьBigDecimal::add
. Есть идеи для этой строкиc.getStates().stream().mapToInt(State::getPopulation).sum()
с BigDecimal?