9 Essential Java Code Optimizations to Eliminate Bad Practices
This article presents nine practical Java code‑optimization techniques—including string formatting, loop refactoring, resource management, buffered I/O, multithreading, enums, exception handling, and third‑party libraries—each illustrated with before‑and‑after code samples and clear explanations of why the improved version is more readable, efficient, and maintainable.
In Java projects, common problems such as chaotic string concatenation, nested loops, unreleased resources, redundant if‑else chains, and duplicated exception handling reduce readability, maintainability, and performance. The following nine optimizations address these issues using Spring Boot 3.5.0 as the runtime environment.
1. Use String.format() or .formatted() for string construction
Concatenating many values with the + operator quickly becomes unreadable, especially for URLs or log messages.
Before:
String url = "http://localhost:8080?name=" + name +
"&age=" + age +
"&address=" + address +
"&sex=" + sex ;Improved version with StringBuilder :
StringBuilder sb = new StringBuilder("http://localhost:8080?");
sb.append("name=").append(name)
.append("&age=").append(age)
.append("&address=").append(address)
.append("&sex=").append(sex);
String url = sb.toString();More concise version with String.format :
String requestUrl = "http://localhost:8080?name=%s&age=%s&address=%s&sex=%s";
String url = String.format(requestUrl, name, age, address, sex);For Java 15+, the same can be written as "...".formatted(name, age, address, sex). Note: avoid String.format() inside large loops because it is slower than StringBuilder .
2. Reduce nested loops
Deeply nested loops increase the total number of operations dramatically (e.g., two lists of 10,000 elements lead to 100 million comparisons).
Before:
for (Order order : orders) {
for (Product product : products) {
if (order.getProductId().equals(product.getId())) {
order.setProductName(product.getName());
}
}
}After: build a map of products keyed by ID, then look up directly.
Map<Long, Product> productMap = products.stream()
.collect(Collectors.toMap(Product::getId, product -> product));
for (Order order : orders) {
Product product = productMap.get(order.getProductId());
if (product != null) {
order.setProductName(product.getName());
}
}3. Properly close resources with try‑with‑resources
Leaving JDBC connections, streams, or result sets open can cause resource leaks and eventual application crashes.
Before:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "root");
PreparedStatement pstmt = conn.prepareStatement("select * from t_user");
ResultSet rs = pstmt.executeQuery();
// resources never closedLegacy manual close:
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection(...);
pstmt = conn.prepareStatement(...);
rs = pstmt.executeQuery();
} catch (Exception e) {
// ...
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {}
try { if (pstmt != null) pstmt.close(); } catch (Exception e) {}
try { if (conn != null) conn.close(); } catch (Exception e) {}
}Modern try‑with‑resources:
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "root");
PreparedStatement pstmt = conn.prepareStatement("select * from t_user");
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
}4. Use buffered I/O streams
Reading or writing one byte at a time causes many disk operations and slows down large‑file processing.
Before:
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
int data;
while ((data = fis.read()) != -1) {
fos.write(data);
}
fos.flush();After:
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))) {
byte[] buffer = new byte[4096];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
}Benefits: block‑level reads/writes, fewer disk accesses, better performance for large files, and automatic resource closing via try‑with‑resources.
5. Parallelize independent tasks with CompletableFuture
Sequentially invoking multiple services can lead to long total latency.
Before:
public void fetchData() {
String user = getUserData();
String orders = getOrderData();
String payments = getPaymentData();
// ...
}After:
public void fetchData() {
CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() -> getUserData());
CompletableFuture<String> orderFuture = CompletableFuture.supplyAsync(() -> getOrderData());
CompletableFuture<String> paymentFuture = CompletableFuture.supplyAsync(() -> getPaymentData());
CompletableFuture.allOf(userFuture, orderFuture, paymentFuture).join();
// ...
}Result: independent tasks run concurrently, reducing overall response time, especially for I/O‑bound operations.
6. Represent fixed states with enums
Using raw integers or strings for status values makes code hard to read and error‑prone.
Before:
public class Task {
public static final int PENDING = 1;
public static final int IN_PROGRESS = 2;
public static final int COMPLETED = 3;
private int status;
}After:
public enum TaskStatus {
PENDING,
IN_PROGRESS,
COMPLETED
}7. Eliminate long if‑else chains with a map lookup
Long conditional chains are difficult to maintain and extend.
Before:
public void sendNotification(String type) {
if ("EMAIL".equals(type)) {
sendEmail();
} else if ("SMS".equals(type)) {
sendSMS();
} else if ("PUSH".equals(type)) {
sendPushNotification();
} else {
System.out.println("Unknown notification type");
}
}After:
Map<String, Runnable> notificationMap = new HashMap<>();
notificationMap.put("EMAIL", this::sendEmail);
notificationMap.put("SMS", this::sendSMS);
notificationMap.put("PUSH", this::sendPushNotification);
public void sendNotification(String type) {
Runnable action = notificationMap.get(type);
if (action != null) {
action.run();
} else {
System.out.println("Unknown notification type");
}
}Benefits: clearer code, easier extension, reduced conditional complexity.
8. Centralize exception handling with @RestControllerAdvice
Repeating try‑catch blocks in each controller pollutes the code.
Before:
@GetMapping("/divide")
public int divide(int a, int b) {
try {
return a / b;
} catch (ArithmeticException e) {
return 0;
}
}After:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public ResponseEntity<Object> handleArithmeticException(ArithmeticException ex) {
return ResponseEntity.ok(ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<R> handleGeneralException(Exception ex) {
return ResponseEntity.ok(R.error(ex.getMessage()));
}
}
// Controller now stays simple
@GetMapping("/divide")
public int divide(int a, int b) {
return a / b;
}Advantages: removes duplicated try‑catch, keeps controllers clean, provides consistent error responses, and eases maintenance in large applications.
9. Leverage third‑party libraries to avoid reinventing utilities
Java’s ecosystem offers mature libraries that simplify common tasks.
Guava
Apache Commons
Jackson
Example: replace a manual string‑blank check with Apache Commons’ StringUtils.isBlank:
import org.apache.commons.lang3.StringUtils;
boolean result = StringUtils.isBlank(str);Using well‑tested libraries reduces boilerplate, improves readability, and minimizes bugs.
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.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.
