Можно ли преобразовать из HashMap в список с помощью MapStruct

Я знаю, что есть аналогичный вопрос (см. вопрос), но я не нашел там полезного ответа. Допустим, у меня есть следующие классы:

class QuestionType {
    private String type;
}

class Profile {
    private String name;
    private int id;
}

class ProfileResponse {
    private String name;
    private int id;
    private String type;
}

Как я мог преобразовать HashMap<QuestionType, Profile> в List<ProfileResponse> с помощью MapStruct (1.3.1)

@Mapper(componentModel = "spring")
public interface ProfileResponseMapper {
    List<ProfileResponse> toProfileResponse(Map<QuestionType, Profile> profiles);
}

person thmasker    schedule 23.10.2020    source источник


Ответы (2)


MapStruct не имеет механизма неявного преобразования для отображения Map в List. Однако вы можете сделать трюк, чтобы понять Map как набор Entry и сопоставить каждую запись с элементом списка:

@Mapper(componentModel = "spring")
public interface ProfileResponseMapper {

    @Mapping(target = "type", source = "key.type")
    @Mapping(target = "name", source = "value.name")
    @Mapping(target = "id", source = "value.id")
    ProfileResponse map(Map.Entry<QuestionType, Profile> profile);
        
    default List<ProfileResponse> toProfileResponse(Map<QuestionType, Profile> map) {
        return map.entrySet()
                  .stream()
                  .map(this::map)
                  .collect(Collectors.toList());
    }
}
ProfileResponseMapper mapper = ...    // ProfileResponseMapper.INSTANCE or @Autowired 
Map<QuestionType, Profile> map = ...  // input Map

List<ProfileResponse> profileResponseList = mapper.toProfileResponse(map);

Код использует преимущества методов Java 8 default и Stream API, в противном случае используйте abstract class и цикл for-each.

person Nikolas Charalambidis    schedule 23.10.2020
comment
Я бы сделал это даже на Java 11 (на самом деле я пробовал этот пример с Java 11, но функции default и Stream API взяты из Java 8). Если у вас возникли проблемы с моим решением, просьба уточнить, код пока работает у меня. - person Nikolas Charalambidis; 23.10.2020

Я бы предпочел следовать принципу KISS: итерации через двухпотребителя по карте, создание объектов ProfileResponse и их внесение в список.

map.forEach (key, val -> 
    {
        ProfileRespone respone = new ProfileResponse(key.type, val.name, val.id);
        list.add(response);
    }
person Community    schedule 23.10.2020