15 Essential Java Backend Optimization Tips to Boost Performance
This article shares practical Java backend best‑practice tips—ranging from reordering conditional checks and avoiding unnecessary object creation to efficient database queries, proper logging, idempotent APIs, and smart caching—to help developers write faster, safer, and more maintainable code.
Introduction
After completing a recent feature, I reflected on several code patterns that could be improved for better performance and reliability. Below are concise best‑practice recommendations for Java backend development.
1. Reorder Complex Logical Conditions
When checking both isUserVip and isFirstLogin, placing the condition that is cheaper to evaluate first reduces the number of executions. For example, swapping the order so that isFirstLogin && isUserVip is evaluated first reduces isUserVip checks from five to one.
if (isFirstLogin && isUserVip) {
sendMsg();
}2. Avoid Unnecessary Object Creation
Repeatedly creating Calendar and Date objects inside a method wastes resources. Extract immutable objects as static constants and reuse them.
public class Test {
private static final Date BEGIN_TIME;
private static final Date END_TIME;
static {
Calendar gmtCal = Calendar.getInstance();
gmtCal.set(2019, Calendar.JANUARY, 1, 0, 0, 0);
BEGIN_TIME = gmtCal.getTime();
gmtCal.set(2020, Calendar.JANUARY, 1, 0, 0, 0);
END_TIME = gmtCal.getTime();
}
public boolean isUserVIPValid() {
Date now = new Date();
return now.compareTo(BEGIN_TIME) >= 0 && now.compareTo(END_TIME) <= 0;
}
}3. Fetch Only Required Data from the Database
Instead of selecting all columns with SELECT *, specify only the needed fields. Also, avoid loading entire result sets when a single row suffices.
// Bad: fetch all user IDs then filter in Java
List<Long> userIds = sqlMap.queryList("select userId from user where vip=1");
boolean isVip = userIds.contains(userId);
// Good: let the DB filter directly
Long userId = sqlMap.queryObject("select userId from user where userId='" + userId + "' and vip='1'");
bool isVip = userId != null;4. Isolate Non‑Critical Notification Calls
When a notification service fails, it should not block the main business flow. Wrap the call in a try‑catch block or execute it asynchronously.
try {
sendMsgNotify();
} catch (Exception e) {
log.error("Notification failed", e);
}
// or
new Thread(() -> sendMsgNotify()).start();5. Prevent NullPointerException by Using Constant‑First Equality Checks
Write comparisons as "1".equals(user.getUserFlag()) to avoid NPE when user.getUserFlag() is null.
6. Add Sufficient Logging
Log method entry, parameters, and errors with appropriate log levels. Do not misuse error level for normal informational messages.
public void transfer(TransferDTO dto) {
log.info("invoke transfer begin");
log.info("invoke transfer, parameters:{}", dto);
try {
// business logic
} catch (Exception e) {
log.error("transfer fail, cifno:{}, account:{}, exception:{}", dto.getCifno(), dto.getAccount(), e);
}
log.info("invoke transfer end");
}7. Split Large Functions into Small, Focused Methods
Break down functions that exceed a few hundred lines into smaller units with clear responsibilities, improving readability and testability.
public void printOwing() {
printBanner();
double total = getTotalAmount();
printDetail(total);
}
private void printBanner() { System.out.println("****************"); }
private double getTotalAmount() { /* calculate */ }
private void printDetail(double amount) { /* print */ }8. Externalize Configurable Elements
Store variable UI assets such as red‑packet skins in a configuration table instead of hard‑coding if branches. Changing a skin then only requires a data update.
9. Remove Unused Imports and Variables
Delete any import statements, local variables, or fields that are never referenced to reduce compilation overhead.
10. Ensure Proper Index Usage
For tables with more than 100,000 rows, create indexes on frequently queried columns. Avoid patterns that invalidate indexes, such as leading LIKE wildcards or functions on indexed columns.
11. Return Empty Collections Instead of Null
Returning Collections.EMPTY_LIST prevents callers from encountering NPE when iterating over results.
12. Pre‑size Collections
When the expected size is known, initialize collections with an appropriate capacity to avoid resizing overhead.
Map<String, Object> map = new HashMap<>(21); // for ~15 entries (15/0.75+1)13. Process Large Data Sets in Batches
When updating many rows, fetch and process them in batches (e.g., 500 records) to limit memory consumption.
int count = sqlMap.queryCount("select count(1) from Order where status='0'");
while (true) {
int size = sqlMap.batchUpdate(params);
if (size < 500) break;
}14. Design Idempotent APIs
Ensure that repeated requests have the same effect as a single request. For example, check and set a status flag atomically before starting a download.
if (updateExcelStatus(1)) {
downLoadExcel();
} else {
System.out.println("File is already downloading");
}15. Use a Private Constructor for Utility Classes
Declare a private constructor to prevent accidental instantiation of classes that only contain static helper methods.
public class StringUtils {
private StringUtils() { /* prevent instantiation */ }
public static boolean validateString(String str) { /* ... */ }
}16. Cache Invariant User Data
Cache rarely changing data (e.g., user age) to reduce repetitive database hits and improve overall response time, especially for high‑traffic features like live‑stream listings.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
