Переопределенный метод toString() возвращает hashCode

Проблема состоит в том, что при попытке переопределения List, запрос все равно возвращает hashCode. Позвольте объяснить.

У меня есть дочерний класс ContactWrapper, который имеет такие атрибуты как: contactType и contact. Родительский класс PersonResponceWrapper, помимо своих атрибутов, имеет поле List<ContactWrapper>.

Проблем не возникает, если персона имеет всего один контакт. Элементарное переопределение toString() в дочернем классе возвращает нам читабельный вид типа: "Phone: 8(800)-555-35-35". Но если контактов несколько, необходимо переопределять toString() в родительском классе, и вот здесь кроется проблема.

Я пытался решить это таким образом:

@Override
public String toString() {
    List<ContactWrapper> contactList = getContacts();
    String string = "";
    for (ContactWrapper contact:contactList) {
        string = contact.getContactType() + ": " + contact.getContact + "; ";
    }
    return string;
}

Это метод, который записывает БД в csv файл:

public byte[] generateReport() throws IOException {
    File targetFile = new File(FILE_NAME);
    try {
        Writer writer = Files.newBufferedWriter(targetFile.toPath());

        StatefulBeanToCsv<PersonResponseWrapper> csvWriter = new StatefulBeanToCsvBuilder<PersonResponseWrapper>(writer)
                .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
                .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
                .withEscapechar(CSVWriter.DEFAULT_ESCAPE_CHARACTER)
                .withLineEnd(CSVWriter.DEFAULT_LINE_END)
                .withOrderedResults(false)
                .build();

        List<Person> personList = (List<Person>) personRepository.findAll();

        csvWriter.write(personList.stream().map(PersonResponseWrapper::new).collect(Collectors.toList()));

        writer.close();

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    byte[] result = Files.readAllBytes(targetFile.toPath());
    targetFile.delete();
    return result;
}

Конструктор PersonResponceWrapper:

public PersonResponseWrapper(Person person) {
    this.id = person.getId();
    this.name = person.getName();
    this.surname = person.getSurname();
    this.patronymic = person.getPatronymic();
    this.birthDate = person.getBirthDate();
    if(CollectionUtils.isNotEmpty(person.getContacts())) {
        contacts = person.getContacts().stream().map(v -> new ContactWrapper(v.getId(),
                                                  v.getContactType(), v.getContact())).collect(Collectors.toList());
    }
}

Вот такой вывод я получаю, вне зависимости, переопределен метод toString() в родительском классе, или нет:

Элементарное переопределение в дочернем классе ContactWrapper работает, но не в случае, когда контактов больше чем один:


Всем спасибо за оказанное внимание.


Ответы (2 шт):

Автор решения: V-CHO

Попробуйте написать вот так:

contacts = person.getContacts().stream().map(ContactWrapper::new).collect(Collectors.toList());

а сам ContactWrapper cделать через конструктор на основе Contact типа:

    public ContactWrapper(Contact contact) {
        this.id = contact.getId();
        this.contact = contact.getContact();
        this.contactType = contact.getContactType();
        //...
    }
→ Ссылка
Автор решения: Никита Царев

Создаем класс PrintReport, в котором конструктор принимает сущность Person, за исключением List<Contact>. Вместо этого мы присваиваем атрибуту String contact значения contactType и contact циклом:

public class PrintReport {
    private Long id;
    private String name;
    private String surname;
    private String patronymic;
    private LocalDate birthDate;
    private String contacts = "";

    public PrintReport() {
    }

    public PrintReport(Person person) {
        this.id = person.getId();
        this.name = person.getName();
        this.surname = person.getSurname();
        this.patronymic = person.getPatronymic();
        this.birthDate = person.getBirthDate();
        for (Contact contact:person.getContacts()) {
            this.contacts += contact.getContactType() + ": " + contact.getContact() + "; ";
        }
    }
}

Затем заменяем PersonResponceWrapper на PrintReport в методе записи csv файла generateReport():

public byte[] generateReport() throws IOException {
    File targetFile = new File(FILE_NAME);
    try {
        Writer writer = Files.newBufferedWriter(targetFile.toPath());

        StatefulBeanToCsv<PrintReport> csvWriter = new StatefulBeanToCsvBuilder<PrintReport>(writer)
                .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
                .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
                .withEscapechar(CSVWriter.DEFAULT_ESCAPE_CHARACTER)
                .withLineEnd(CSVWriter.DEFAULT_LINE_END)
                .withOrderedResults(false)
                .build();

        List<Person> personList = (List<Person>) personRepository.findAll();

        csvWriter.write(personList.stream().map(PrintReport::new).collect(Collectors.toList()));

        writer.close();

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    byte[] result = Files.readAllBytes(targetFile.toPath());
    targetFile.delete();
    return result;
}

В конечном счете, метод toString() переопределять не пришлось.
Всем большое спасибо за обсуждение и участие!:)

→ Ссылка