Home Lombok Lombok @Singular Examples with Builders

Lombok @Singular Examples with Builders

In this article we will look into several examples using Lombok @Singular annotation and how it works with collection valued fields like IterableCollectionMap 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 :

  1. One ‘adder’ method for adding single element to collection.
  2. Another ‘adder’ method for adding another collection to the collection, this name is plural for the field name .
  3. 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 IterableCollectionMap 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 :

  1. Lombok @Getter @Setter and lazy getters examples
  2. Lombok @Data
  3. Lombok @Value
  4. Lombok @Builder
  5. Lombok Builder default values Examples
  6. Lombok @NonNull
  7. Lombok Spring Boot example
Satish Varma
Satish Varmahttps://javabydeveloper.com
Satish is post graduated in master of computer applications and experienced software engineer with focus on Spring, JPA, REST, TDD and web development. Follow him on LinkedIn or Twitter or Facebook

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Stay in Touch

Categories