Преобразование объектов коллекции одного типа в объекты другого с помощью Stream API и ссылочных методов - PullRequest
1 голос
/ 26 мая 2020

Я использую лямбда для преобразования объектов одного типа в объекты другого

  • Order
@JacksonXmlRootElement(localName = "order")
public class Order {

    private String customer;

    @JacksonXmlProperty(localName = "orderItem")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<OrderItem> orderItems = new ArrayList<>();

    public Order() {
    }

  • OrderDto
public class OrderDto {

     private String customer;

     private String orderXml;

    public OrderDto() {
    }
  • service
@Service
public class OrderReadServiceImpl implements OrderReadService {

    private OrderEntityRepository repository;

    private OrderDtoMapper mapper;

    private CycleAvoidingMappingContext context;

    @Autowired
    public OrderReadServiceImpl(OrderEntityRepository repository,
                                OrderDtoMapper mapper,
                                CycleAvoidingMappingContext context) {
        this.repository = repository;
        this.mapper = mapper;
        this.context = context;
    }

    @Override
    public Iterable<Order> getListOrder() {

        Iterable<OrderEntity> orderEntities = this.repository.findAll();

        Iterable<Order> orders = convertXmlToListObj(orderEntities);

        return orders;
    }

    private Iterable<Order> convertXmlToListObj(Iterable<OrderEntity> entities) {

        Iterable<OrderDto> dtoList = toListDto(entities);

        Iterable<Order> orders = convertListToList(dtoList);

        return orders;
    }

    /**
     * There is convert a collection of objects one type to another type
     * @param dtoList
     * @return
     */
    private static Iterable<Order> convertListToList(Iterable<OrderDto> dtoList) {

        List<OrderDto> list = new ArrayList<>();
        dtoList.forEach(list::add);

        List<Order> collect = list.stream()
            .map(orderDto -> {
                Order order = convertXmlToObj(orderDto);
                return order;
            }).collect(Collectors.toList());

        return collect;
    }

    /**
     * there is got a string that xml. This xml is convert to java object
     * @param orderDto
     * @return
     */
    private static Order convertXmlToObj(OrderDto orderDto) {

        String orderXml = orderDto.getOrderXml();

        StringReader reader = new StringReader(orderXml);

        Order order = JAXB.unmarshal(reader, Order.class);

        return order;
    }

    /**
     * transform objects of  entity type to objects of dto types
     * @param entities
     * @return
     */
    private Iterable<OrderDto> toListDto(Iterable<OrderEntity> entities) {
        return this.mapper.toListDto(entities);
    }
}

Результирующий список сущностей преобразуется в коллекцию dto . Коллекция преобразованного списка dto повторяется и извлекается оттуда xml из поля каждого элемента коллекции, а затем структура этого xml будет umarshall ( то есть список из xml элементов будет преобразован в коллекцию java объектов)

        List<OrderDto> list = new ArrayList<>();
        dtoList.forEach(list::add);

        List<Order> collect = list.stream()
            .map(orderDto -> {
                Order order = convertXmlToObj(orderDto);
                return order;
            }).collect(Collectors.toList());

        return collect;

Я бы хотел сделать самое простое. Хочу, чтобы кода было еще меньше.

Можно код где-нибудь убрать, как уменьшить.

То есть. Где мне еще создать «ссылки на методы».

У кого есть идеи, как это сделать?

Ответы [ 2 ]

3 голосов
/ 26 мая 2020

Вы можете преобразовать Iterable в Stream напрямую, не создавая List:

StreamSupport.stream(dtoList.spliterator(), false)

Ваш код может стать

private static Iterable<Order> convertListToList(Iterable<OrderDto> dtoList) 
{
    return StreamSupport.stream(dtoList.spliterator(), false)
        .map(orderDto -> convertXmlToObj(orderDto))
        .collect(Collectors.toList());
}

Или со ссылкой на метод:

private static Iterable<Order> convertListToList(Iterable<OrderDto> dtoList) 
{
    return StreamSupport.stream(dtoList.spliterator(), false)
        .map(OrderReadServiceImpl::convertXmlToObj)
        .collect(Collectors.toList());
}

Кстати, поскольку ваш метод назван convertListToList(), возможно, он должен принимать и возвращать List s вместо Iterable s.

0 голосов
/ 26 мая 2020

Если вы хотите решить проблему сопоставления объектов в целом и не ищете точной оптимизации вашего решения лямбда / потока, вы можете взглянуть на MapStruct . Упрощенное описание: он генерирует картографы с помощью аннотаций во время компиляции.

...