In this article we will look into several examples using Lombok @Singular annotation and how it works with collection valued fields like Iterable, Collection, Map and List etc.
Make sure you already installed Lombok setup for your IDE. To Setup in Eclipse or in Spring Tool Suite refer to our Lombok Maven example setup with Eclipse.
The @Singular annotation is used together with Lombok @Builder annotation. If you annotate one of the collection valued field with @Singular
annotation Lombok generates for the field :
- One ‘adder’ method for adding single element to collection.
- Another ‘adder’ method for adding another collection to the collection, this name is plural for the field name .
- Clear method to clear collection elements.
1. @Singular example with List
Lomboked LombokSingularDemo1.java
@Builder(builderClassName = "Builder") @Getter @ToString public class LombokSingularDemo1 { private Long id; @Singular private List<String> names; }
Testing Lomboked LombokSingularDemo1.java
public class LombokSingularDemo1Test { public static void main(String[] args) { LombokSingularDemo1 lsd1 = LombokSingularDemo1.builder() .id(Long.valueOf(1)) .name("peter") .names(List.of("Mark", "Gerhard")) .build(); System.out.println(lsd1); LombokSingularDemo1 lsd2 = lsd1.builder().clearNames().build(); System.out.println(lsd1); System.out.println(lsd2); } }
Output Results :
LombokSingularDemo1(id=1, names=[peter, Mark, Gerhard]) LombokSingularDemo1(id=1, names=[peter, Mark, Gerhard]) LombokSingularDemo1(id=null, names=[])
NOTE : When invoking build()
, the produced collection will be immutable. Calling adder/clear method again after invoke build()
on same instance does not modify any already generated objects and when build()
called again a new instance will be created.
If you annotate @Singular
on the field which is named with singular (ex: name instead names in above example), you will get compile time error “Can’t singularize this name; please specify the singular explicitly (i.e. @Singular(“sheep”))”
DeLomboked LombokSingularDemo1.java
public class LombokSingularDemo1 { private Long id; private List<String> names; LombokSingularDemo1(final Long id, final List<String> names) { this.id = id; this.names = names; } public static class Builder { private Long id; private java.util.ArrayList<String> names; Builder() { } public LombokSingularDemo1.Builder id(final Long id) { this.id = id; return this; } public LombokSingularDemo1.Builder name(final String name) { if (this.names == null) this.names = new java.util.ArrayList<String>(); this.names.add(name); return this; } public LombokSingularDemo1.Builder names(final java.util.Collection<? extends String> names) { if (names == null) { throw new NullPointerException("names cannot be null"); } if (this.names == null) this.names = new java.util.ArrayList<String>(); this.names.addAll(names); return this; } public LombokSingularDemo1.Builder clearNames() { if (this.names != null) this.names.clear(); return this; } public LombokSingularDemo1 build() { java.util.List<String> names; switch (this.names == null ? 0 : this.names.size()) { case 0: names = java.util.Collections.emptyList(); break; case 1: names = java.util.Collections.singletonList(this.names.get(0)); break; default: names = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.names)); } return new LombokSingularDemo1(this.id, names); } @Override public String toString() { return "LombokSingularDemo1.Builder(id=" + this.id + ", names=" + this.names + ")"; } } public static LombokSingularDemo1.Builder builder() { return new LombokSingularDemo1.Builder(); } // Omitted getters and toString() }
2. @Singular example with Map
For Map, Builder adder methods take a key and value of the appropriate types.
@Builder(builderClassName = "Builder") @Getter @ToString public class LombokSingularDemo2 { private Long id; @Singular private Map<Integer, String> students; }
Testing LombokSingularDemo2 :
public class LombokSingularDemo2Test { public static void main(String[] args) { LombokSingularDemo2 lsd2 = LombokSingularDemo2.builder() .id(Long.valueOf(1)) .student(1, "Peter") .student(2, "Martin") .students(Map.of(3, "Philip", 4, "Gerhard")) .students(Map.of(5, "Alisa")) .build(); System.out.println(lsd2); } }
Output Results :
LombokSingularDemo2(id=1, students={1=Peter, 2=Martin, 3=Philip, 4=Gerhard, 5=Alisa})
3. @Singular ignoreNullCollections
In first example you can notice in DeLomboked LombokSingularDemo1.java that names
method have a null
check and throws a NullPointerException
with an appropriate message. To ignore null
check you can set attribute ignoreNullCollections
value to true
, default value is false
. Note that this is possible in version since v1.18.8.
4. Custom name for @Singular methods
For example, the singular and plural forms are the same for word “aircraft” is same As we already noted in example 1, If you annotate @Singular
on the field which is named aircraft , you will get compile time error “Can’t singularize this name; please specify the singular explicitly (i.e. @Singular(“sheep”))”
We can resolve this by providing value to the @Singular
annotation like @Singular("singleAircraft")
.
@Builder(builderClassName = "Builder") @Getter @ToString public class LombokSingularDemo3 { private Long id; @Singular("singleAircraft") private List<String> aircraft; }
Testing LombokSingularDemo3 :
public class LombokSingularDemo3Test { public static void main(String[] args) { LombokSingularDemo3 lsd3 = LombokSingularDemo3.builder() .id(Long.valueOf(1)) .singleAircraft("Boeing XP-15") .singleAircraft("Avro 527") .aircraft(List.of("Sukhoi Su 47", "Supermarine 535")) .build(); System.out.println(lsd3); } }
Output Results :
LombokSingularDemo3(id=1, aircraft=[Boeing XP-15, Avro 527, Sukhoi Su 47, Supermarine 535])
5. Conclusion
In this article we have looked into several examples using Lombok @Singular annotation and how it works with collection valued fields like Iterable, Collection, Map and List etc.
You can refer Delombok Maven example to see how looks like lombok generated code for your Lomboked classes.
You can checkout source code at github.
You might be interested in our other following Lombok Tutorials :