size() and isEmpty()
Counts the elements in a list and checks for an empty one, plus the null-versus-empty and capacity mistakes around them.
int size()
boolean isEmpty()- Added in Java Java 1.2
Return value
int / booleansize() returns the number of elements, capped at Integer.MAX_VALUE. isEmpty() returns true when the list has no elements.
Errors
Neither method throws on a standard list. Calling either on a null reference throws NullPointerException.
size() returns how many elements the list holds. isEmpty() returns true when that number is zero. Java lists have no length field; that is for arrays, and strings use length(). Mixing the three up is a common compile error for people coming from other languages.
isEmpty reads better
list.isEmpty() and list.size() == 0 give the same answer on every standard list. Prefer isEmpty(): it says what you are asking, and for some collections it is cheaper than counting. For ArrayList, LinkedList and List.of lists, both are constant time.
Null is not empty
Calling isEmpty() on a null reference throws NullPointerException. The fix is upstream: methods that return lists should return an empty list, never null. A repository query that finds nothing returns List.of(), and the caller can loop over it or check isEmpty() without a special case. Frameworks follow the same rule, and JSON serialisers turn an empty list into [], which is what API clients expect.
When a list does arrive from somewhere you do not control, such as a deserialised request body, check list == null || list.isEmpty() once at the boundary and replace null with an empty list.
Size is not capacity
new ArrayList<>(100) reserves room for 100 elements but its size() is 0. Capacity is an internal detail of ArrayList with no getter; size() only counts elements you have added.
Views and concurrency
- A
subListorreversed()view reports its own size, and changes made through it change the original list's size too. - In shared, concurrently modified lists,
if (!list.isEmpty()) list.get(0)is a check-then-act race: another thread can empty the list between the two calls. Keep request data in local lists, or use a structure built for concurrent access.
size() is what you use to compute page counts, to report totals in a response, and to enforce limits such as a maximum of 100 items per batch request.
Example
When to use it
- Returning 400 Bad Request when a list of validation errors is not empty.
- Computing total pages and item counts for a paginated API response.
- Rejecting a batch request that contains more items than the endpoint allows.
Frequently asked questions
How do I get the length of a list in Java?
Call list.size(). Lists have no length field or length() method; length is for arrays and length() is for strings.
Should I use isEmpty() or size() == 0?
They give the same result, but isEmpty() states the intent and is never slower, so prefer it.
How do I check if a list is null or empty?
Write list == null || list.isEmpty(), with the null check first. Better still, make methods return an empty list instead of null so the null check is not needed.
More examples
Page count and the last page
Integer division rounded up gives the page count from size(). Clamping the end index with Math.min keeps the last, shorter page in bounds.
void main() {
List<Integer> ids = IntStream.rangeClosed(1, 23).boxed().toList();
int pageSize = 10;
int pages = (ids.size() + pageSize - 1) / pageSize;
IO.println("total=" + ids.size() + " pages=" + pages);
int from = (pages - 1) * pageSize;
List<Integer> last = ids.subList(from, Math.min(from + pageSize, ids.size()));
IO.println("last page: " + last + " (" + last.size() + " items)");
}
// Output:
// total=23 pages=3
// last page: [21, 22, 23] (3 items)Empty list instead of null
The method returns a list in every case, empty when nothing matches, so callers can call size() or isEmpty() straight away. A REST layer would serialise the empty result as [].
record Article(String title, String tag) {}
List<Article> findByTag(List<Article> all, String tag) {
return all.stream()
.filter(a -> a.tag().equals(tag))
.toList();
}
void main() {
List<Article> all = List.of(new Article("Records", "java"), new Article("Joins", "sql"));
IO.println(findByTag(all, "java").size());
List<Article> none = findByTag(all, "rust");
IO.println(none.isEmpty() ? "no articles" : none.toString());
}
// Output:
// 1
// no articlesCapacity is not size
The constructor argument reserves space but adds nothing. size() is the real count, which is what a per-request item limit should test.
void main() {
List<String> batch = new ArrayList<>(100);
IO.println(batch.size() + " " + batch.isEmpty());
int max = 2;
for (String item : List.of("a", "b", "c")) {
if (batch.size() >= max) {
IO.println("batch full, rejected " + item);
continue;
}
batch.add(item);
}
IO.println(batch);
}
// Output:
// 0 true
// batch full, rejected c
// [a, b]
Discussion