Using @Singular with @Builder annotation example

In this post under Lombok I will explain with example the purpose of “@Singular” annotation which is alwayse used with “@Builder” annotation.

In previous post under lombok I have explained why we use “@Builder” annotation i.e., to implement builder pattern.

So if have below pojo class with “@Builder” annotation at the class level

Pojo class

package package26;

import lombok.Builder;

@Builder
public class Person {
    private String name;
    private String city;

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(name).append(":");
        stringBuilder.append(city);

        return stringBuilder.toString();
    }
}

We can build the Person object as shown below

Person person = Person.builder()
                .name("Adam Savage")
                .city("San Francisco")
                .build();

In the above Pojo class we used only single value properties and lombok’s “@Builder” annotation created methods with same name and which takes single value arguments.

But what if there is a collection property in pojo class as shown below

Pojo class with collection property

package package26;

import java.util.List;

import lombok.Builder;

@Builder
public class Person {
    private String name;
    private String city;
    private List<String> jobs;

    @Override
    public String toString() {
        ...
    }
}

We can build the Person object as shown below

    List<String> list = new ArrayList<String>(0);
        list.add("Mythbusters");
        list.add("Unchained Reaction");

        Person person = Person.builder()
                .name("Adam Savage")
                .city("San Francisco")
                .jobs(list)
                .build();

Lombok will create method with same name as collection property but accepts a collection as an argument.

In our example, it will create a method with name “jobs” which is same as collection property “jobs” and accepts “List” as argument.

We have to create a list by ourself and pass it as argument to the “jobs” method.

But what if you want a method which accepts single value argument and internally add the passed single value argument to its own collection.

I mean if we take our previous example, we want a method “job” which will take a single String value as argument and add it to internally created “jobs” collection.

We can achieve this by using “@Singular” annotation. It is applied at the collection property, which in our case is “jobs” as shown below

package package27;

import java.util.List;

import lombok.Builder;
import lombok.Singular;

@Builder
public class Person {
    private String name;
    private String city;
    @Singular
    private List<String> jobs;

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(name).append(":");
        stringBuilder.append(city).append(":");
        stringBuilder.append("{");
        for(String data : jobs) {
            stringBuilder.append(data).append(",");
        }
        stringBuilder.append("}");
        return stringBuilder.toString();
    }
}

We can create the Person object as shown below

        Person person = Person.builder()
                .name("Thomas Jefferson")
                .city("Fairfax")
                .job("Mythbusters")
                .job("Unchained Reaction")
                .build();

In the above code, we called “job” method twice and passed the two arguments one by one instead of passing a collection as an argument.

Both the arguments “Mythbusters” and “Unchained Reaction” are added in “jobs” collection created internally.

In this way we can use “@Singular” annotation with “@Builder” annotation.

Below is the output

Output

Thomas Jefferson:Fairfax:{Mythbusters,Unchained Reaction,}

Leave a comment