Строитель с лямбда-выражением для Java 8 - PullRequest
0 голосов
/ 05 мая 2020

У меня есть два класса, как указано ниже. Я хотел создать два экземпляра class A.

Я хочу создать экземпляр obj2 из существующего экземпляра obj1 с обновленным значением атрибута a3 как "Java".

Я пробовал использовать строку ниже, используя Builder , но она не работает.

A obj2 = obj1.builder().a3("Java").build();

Я могу сделать это с помощью вызывающего конструктора, но я хотел это сделать Builder только шаблон.

@Builder(toBuilder = true)
@Data
class A {
    String a1;
    String a2;
    String a3;
    B b;

    A(String b1, String b2, String b3, B b) {
        this.a1 = b1;
        this.a2 = b2;
        this.a3 = b3;
        this.b = b;
    }
}

@Builder
@Data
class B {
    String b1;
    String b2;
    String b3;

    B(String b1, String b2, String b3) {
        this.b1 = b1;
        this.b2 = b2;
        this.b3 = b3;
    }

}

class Main {
    public static void main(String[] args) {

        B b = new B("a", "b", "b");
        A obj1 = new A("a1", "b1", "b1", b);
        A obj2 = new A("x1", "y1", "z1", b);
        List<A> list= new ArrayList<>();
        list.add(obj1);
        list.add(obj2);
        list.forEach(a -> {
            a.toBuilder().a1("newA1").a2("newA2").build();
            repository.save(a);
        });

        A obj3 = obj1.toBuilder().a3("Java").build();
    }
}

Как упоминалось в обновленном коде, у меня есть список A, и я хочу обновить a1 and a2 атрибуты всего элемента в списке с помощью построителя. Но строитель не работает с лямбдой. Если я буду использовать сеттер с приведенным ниже кодом, он работает нормально.

list.forEach(a -> {
    a.setA1("newA1");
    a.setA2("newA2");
});

Я не могу получить обновленные значения для a1 and a2 в случае Builder с Lambda

Ответы [ 2 ]

5 голосов
/ 05 мая 2020

Этот оператор ничего не делает

list.forEach(a -> {
    a.toBuilder().a1("newA1").a2("newA2").build();  //<<<
    repository.save(a);
});

Вы создаете новый объект из старого, а затем выбрасываете его. Он не внесет изменений в существующий объект. Рассмотрим

list.stream()
    .map(a -> a.toBuilder().a1("newA1").a2("newA2").build())
    .forEach(repository::save);
0 голосов
/ 05 мая 2020

Ответ пользователя @Michael уже исправил кучу ваших ошибок при вставке.

Причина «не работает» (пожалуйста, уточните c в следующий раз) в том, что вы делаете без операции.

Операция:

x.toBuilder().changeSomething().build() создает новый объект . Он не изменяет объект: Builder предназначен для неизменяемых объектов; вы не можете их изменить.

Итак, для каждого элемента в списке вы получаете конструктор из него, вносите некоторые изменения, создаете на его основе новый объект, а затем быстро помещаете этот объект в мусор.

попробуйте:

list.stream().map(a -> a.toBuilder().a1("newA1").build()).collect(Collectors.toList());

или более простой вариант:

for (int i = 0; i < list.size(); i++) {
    var withNewValue = list.get(i).toBuilder().a1("newA1").build();
    list.set(i, withNewValue);
}

иногда старые способы - лучшие.

...