Boost Java Performance: 50 Proven Tips for Faster, Efficient Code

This article presents a comprehensive collection of 50 practical Java performance tips, covering constants, variables, objects, methods, expressions, strings, arrays, collections, exceptions, buffers, and threading, each illustrated with clear examples of inefficient code and its optimized counterpart to help developers write high‑efficiency Java applications.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Boost Java Performance: 50 Proven Tips for Faster, Efficient Code

1. Constants & Variables

Use direct constant assignment without creating new objects; prefer static final constants for immutable values; avoid unnecessary boxing/unboxing by using primitive types; define temporary variables inside methods; minimize variable scope; prefer primitive types for method parameters and return values; avoid redundant initializations.

Long i = 1L;
String s = "abc";

1.1 Directly assign constant values, avoid new objects

Long i = 1L;
String s = "abc";

1.2 Use static constants for values that never change

public class HttpConnection {
    private static final long TIMEOUT = 5L;
    ...
}

1.3 Avoid automatic boxing and unboxing

int sum = 0;
int[] values = ...;
for (int value : values) {
    sum += value;
}

1.4 Do not assign an initial value that will be overwritten

List<UserDO> userList;
if (isAll) {
    userList = userDAO.queryAll();
} else {
    userList = userDAO.queryActive();
}

1.5 Use primitive temporary variables inside functions

public final class Accumulator {
    private double result = 0.0D;
    public void addAll(@NonNull double[] values) {
        double sum = 0.0D;
        for (double value : values) {
            sum += value;
        }
        result += sum;
    }
}

1.6 Prefer static methods when no instance state is used

public static int getMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return calendar.get(Calendar.MONTH) + 1;
}

1.7 Use final methods for potential inlining

public final double area() { ... }

2. Objects & Classes

Avoid using JSON libraries for object conversion due to performance overhead; prefer manual mapping. Reduce reflection usage for object assignment; replace anonymous inner classes with lambda expressions for better performance.

// Bad: JSON conversion
List<UserVO> userVOList = JSON.parseArray(JSON.toJSONString(userDOList), UserVO.class);
// Good: manual mapping
List<UserVO> userVOList = new ArrayList<>(userDOList.size());
for (UserDO userDO : userDOList) {
    UserVO userVO = new UserVO();
    userVO.setId(userDO.getId());
    userVOList.add(userVO);
}

2.3 Replace inner anonymous classes with lambdas

Collections.sort(userList, (u1, u2) -> u1.getId().compareTo(u2.getId()));

3. Methods

Declare utility methods as static when they do not depend on instance fields; use primitive types for parameters and return values; annotate non‑null parameters with @NonNull to eliminate null checks; avoid unnecessary method wrappers.

public static double sum(double v1, double v2) { return v1 + v2; }
public static boolean isValid(@NonNull UserDO user) { return Boolean.TRUE.equals(user.getIsValid()); }

4. Expressions

Cache frequently used values to avoid repeated method calls; prefer switch statements over long if‑else chains for multiple constant branches; extract common sub‑expressions to variables.

int userLength = userList.size();
for (int i = 0; i < userLength; i++) { ... }

5. Strings

Use char‑based replace methods instead of string replace; build strings with StringBuilder; avoid ""+ concatenation; prefer String.valueOf for primitive‑to‑string conversion.

StringBuilder sb = new StringBuilder(128);
for (int i = 0; i < 10; i++) {
    if (i != 0) sb.append(',');
    sb.append(i);
}
String result = sb.toString();
String s = String.valueOf(i);

6. Arrays

Use System.arraycopy for copying arrays; when converting collections to arrays, pass an empty array (T[0]) to toArray; use toArray() for Object[] conversion.

int[] targets = new int[sources.length];
System.arraycopy(sources, 0, targets, 0, sources.length);
Integer[] ints = list.toArray(new Integer[0]);
Object[] objs = list.toArray();

7. Collections

Initialize collections with an expected size to avoid re‑allocation; use addAll or Collections.copy instead of manual loops; prefer Arrays.asList for array‑to‑list conversion; iterate directly over collections rather than using index access on non‑random‑access lists; use HashSet for fast containment checks; avoid size() == 0 checks, use isEmpty(); iterate map.entrySet() instead of keySet() + get();

Set<Long> userSet = new HashSet<>(userSize);
Map<Long, UserDO> userMap = new HashMap<>((int)Math.ceil(userSize * 4.0/3));
List<UserVO> userList = new ArrayList<>(userSize);
for (UserDO user : userDOList) {
    userSet.add(user.getId());
    userMap.put(user.getId(), user);
    userList.add(transUser(user));
}

8. Exceptions

Catch specific exceptions instead of generic Exception; avoid catching inside tight loops; do not use exceptions for regular control flow; use null checks instead of catching NullPointerException.

try {
    saveData();
} catch (IOException e) {
    log.error("IO error", e);
} catch (Exception e) {
    log.error("Other error", e);
}

9. Buffers

Allocate StringBuilder/StringBuffer with an appropriate initial capacity; reuse the same buffer by resetting its length; use buffered streams for I/O operations.

StringBuilder sb = new StringBuilder(1024);
sb.append("update t_user set name='").append(name).append("' where id=").append(id);
statement.executeUpdate(sb.toString());
sb.setLength(0);
sb.append("select id, name from t_user where id=").append(id);
ResultSet rs = statement.executeQuery(sb.toString());

10. Threads

In single‑threaded code, prefer non‑thread‑safe classes like StringBuilder; in multi‑threaded environments, use thread‑safe utilities such as AtomicInteger; keep synchronized blocks as small as possible; combine related synchronized sections; reuse thread pools instead of creating new threads.

private final AtomicInteger counter = new AtomicInteger(0);
public void access(Long userId) {
    counter.incrementAndGet();
    // non‑synchronized work
}

private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(10);
public void executeTask(Runnable r) {
    EXECUTOR.execute(r);
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaperformanceoptimizationbest practicescoding
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology innovations.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.