Code Smell 251 – Collections Empty

Code Smell 251 – Collections Empty

Do you want to count collections or know if they are empty?

TL;DR: Use declarative names. Always

Problems

Readability

Cache Invalidation

Performance Penalties

Type Safety

Solutions

Replace count() == 0 and size()==0 usages

Context

isEmpty() and count()==0 seem to be equivalent but have deep differences.

The semantics are clearer.

Skipping this declarative method violating the collection encapsulation might have performance issues.

Sample Code

Wrong

import java.util.EmptyStackException;
import java.util.Stack;

public class SchrodingerStack<T> {
private Stack<T> stack;

public SchrodingerStack() {
stack = new Stack<>();
}

public void push(T item) {
stack.push(item);
}

public T pop() {
if (stack.size() == 0) {
throw new EmptyStackException();
}

T item = stack.pop();
return item;
}

public int size() {
return stack.size();
// This has O(n) linear time
// And the stack might not be fully reachable in memory
// While you wait, the stack isEmpty and notEmpty
// at the same time
}

public static void main(String[] args) {
SchrodingerStack<String> stack = new SchrodingerStack<>();

stack.push(“Siamese”);
stack.push(“Garfield”);

while (stack.size() > 0) {
System.out.println(“Popped element: “ + stack.pop());
}

if (stack.size() == 0 ) {
// Less readable
// violating encapsulation
// and coupled to the implementation
System.out.println(“The stack is empty.”);
} else {
System.out.println(“The stack is not empty.”);
}
}
}

Right

import java.util.EmptyStackException;
import java.util.Stack;

public class SchrodingerStack<T> {
private Stack<T> stack;
private boolean isEmpty;

public SchrodingerStack() {
stack = new Stack<>();
isEmpty = true;
}

public void push(T item) {
stack.push(item);
isEmpty = false;
}

public T pop() {
if (isEmpty()) {
throw new EmptyStackException();
}

T item = stack.pop();
if (stack.isEmpty()) {
isEmpty = true;
}
return item;
}

public boolean isEmpty() {
return isEmpty;
// This has O(1) constant time
}

public int size() {
return stack.size();
// This has O(n) linear time
// And the stack might not be fully reachable in memory
// While you wait, the stack isEmpty and notEmpty
// at the same time
}

public static void main(String[] args) {
SchrodingerStack<String> stack = new SchrodingerStack<>();

stack.push(“Siamese”);
stack.push(“Garfield”);

while (!stack.isEmpty()) {
System.out.println(“Popped element: “ + stack.pop());
}

if (stack.isEmpty()) {
// Semantic operation not violating encapsulation
System.out.println(“The stack is empty.”);
} else {
System.out.println(“The stack is not empty.”);
}
}
}

Detection

[X] Automatic

You can check for this expression using syntax abstraction trees.

Tags

Readability

Level

[X] Beginner

AI Generation

LLMs generate abstractions using empty() functions

AI Detection

Gemini detected the problem of using count() == 0

Conclusion

Using IsEmpty() is recommended for checking if a collection is empty due to its clarity and potential performance benefits.

Relations

Disclaimer

Code Smells are my opinion.

Credits

Photo by Valentin Lacoste on Unsplash

Good programming is good writing.

John Shore

This article is part of the CodeSmell Series.

Leave a Reply

Your email address will not be published. Required fields are marked *