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,}