【问题标题】:Builder with lambda expression for Java 8带有 Java 8 的 lambda 表达式的生成器
【发布时间】:2020-05-05 14:43:08
【问题描述】:

我有两节课,如下所述。 我想创建 class A 的两个实例。

我想从现有实例 obj1 创建实例 obj2,并将 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 属性。但是 builder 不能很好地使用 lambda。 如果我将使用带有以下代码的 setter,它工作正常。

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

BuilderLambda

的情况下,我无法获取 a1 and a2 的更新值

【问题讨论】:

  • 创建现有对象的更新版本根本不是Builder 的用例。有一个实验性的Wither 可以用于此目的。
  • 原来 Wither 被重命名为 With 并在 Lombok 1.18.10 中退出实验:With
  • @DavidConrad 这是一个用例,Lombok 支持它。
  • @Michael 我忘记了toBuilder,因为我自己从不使用它。我赞成你的回答。

标签: java java-8 builder lombok


【解决方案1】:

这个语句没有做任何事情

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);

【讨论】:

  • 我已经启用了它。即使在正常情况下使用相同的方法更新值也可以正常工作。但是当我使用 lambda 表达式时,它不起作用。
  • @SagarGangwal 如果您向我们展示的代码不代表问题,我们应该如何解决您的问题?
  • 我已经添加了确切的代码,并且还提到了相同的工作方法。
  • @SagarGangwal 这不是确切的代码,因为您的代码没有(toBuilder = true)。无论如何,更新我的答案
  • 我已经添加了我的更新代码,而且关于大括号,我在设置更新值后需要执行多项任务。最后需要保存在数据库中。
【解决方案2】:

用户@Michael 的回答已经在粘贴中修复了你的一堆错误。

“它不工作”的原因(请下次更具体)是你在做空操作。

操作:

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);
}

有时老方法是最好的方法。

【讨论】:

    猜你喜欢
    • 2020-10-06
    • 2017-06-02
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多