Только один объект с настраиваемым конструктором logi c полностью инициализируется в цикле - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь сопоставить один объект с другим (Record -> ParsedAddress) с помощью следующего кода:

public class ParsedAddress extends Address {

    private static final Map<Field, Consumer<String>> MAPPINGS = new EnumMap<>(Field.class);


    public ParsedAddress(final Record record, final List<Field> order) {
        super();

        this.mapFields(record, order);
    }

    private void mapFields(final Record record, final List<Field> order) {
        this.setupMapping();

        for (final Map.Entry<Field, Consumer<String>> mapping : MAPPINGS.entrySet()) {
            final Field field = mapping.getKey();
            final String value = record.getField(field, order);
            final Consumer<String> setter = mapping.getValue();

            setter.accept(value);
        }
    }

    private void setupMapping() {
        if (!MAPPINGS.isEmpty()) return;

        MAPPINGS.put(SALUTATION, this::setSalutation);
        MAPPINGS.put(FIRST_NAME, this::setFirstName);
        MAPPINGS.put(SURNAME, this::setSurname);
        // etc...
    }
}

(Address - это объект данных, содержащий все сопоставленные полей.)

Я вызываю конструктор следующим образом:

records.stream()
       .map(record -> new ParsedAddress(record, ORDER))
       .collect(toUnmodifiableList());

Но отображается только первая «запись». Коллекция результатов содержит один ParsedAddress со всеми данными (так что logi c работает нормально) и ParsedAddress es с null полями.

Я отладил его и сумел сузить проблему до строки setter.accept(value). Он работает точно так же, независимо от того, вызывается ли конструктор внутри потока или в oop.

Это что-то связано с инициализацией объекта? Но тогда почему ровно один объект отображается успешно, а остальные нет?

EDIT : Класс Record содержит только данные, которые должны отображаться. Вот метод getField:

public String getField(final Field field, final List<Field> order) {
    final int index = order.indexOf(field);

    return index == -1 ? null : this.data.get(index);
}

1 Ответ

1 голос
/ 16 июня 2020

Проблема здесь в том, что карта MAPPINGS является статической c с отложенной загрузкой, а ключевое слово this - нет.

Это приводит к тому, что карта заполняется ровно один раз но со ссылками на publi c установщики самого первого объекта, который его достиг (тот, который лениво загрузил карту).

Таким образом, каждый потребитель в MAPPINGS является установщиком publi c для тот же объект (тот, который лениво загрузил карту).

Это было весело!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...