30+ Java Refactoring Tricks to Write Cleaner, Faster Code
This article presents a comprehensive collection of Java code‑simplification techniques—from ternary operators and enhanced for‑loops to streams, Optional, design patterns, and aggressive dead‑code removal—showing how each shortcut can reduce boilerplate, improve readability, and boost performance in backend development.
1. Use Ternary Expressions
Replace verbose if‑else assignments with concise ternary operators.
String title = isMember(phone) ? "会员" : "游客";2. Use Enhanced For‑Each Loops
Iterate over arrays or collections without manual index handling.
for (double value : values) {
// TODO: process value
}3. Use try‑with‑Resources
Automatically close resources that implement Closeable.
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
// TODO: process line
}
} catch (IOException e) {
log.error("读取文件异常", e);
}4. Return Early with return
Eliminate intermediate variables by returning directly.
public boolean hasSuper(@NonNull List<UserDO> userList) {
for (UserDO user : userList) {
if (Boolean.TRUE.equals(user.getIsSuper())) {
return true;
}
}
return false;
}5. Apply static Keyword
Make utility methods and constants static to avoid object creation.
public final class GisHelper {
public static double distance(double lng1, double lat1, double lng2, double lat2) {
// calculation
}
}6. Leverage Lambda Expressions
Replace anonymous inner classes with lambdas for brevity.
new Thread(() -> {
// thread logic
}).start();7. Use Method References
Further shorten lambdas when they merely forward a call.
List<Long> ids = users.stream()
.map(UserDO::getId)
.collect(Collectors.toList());8. Static Imports
Import static members to drop class qualifiers.
import static java.lang.Math.PI;
import static java.lang.Math.pow;
double area = PI * pow(radius, 2);9. Unchecked Exceptions
Wrap checked exceptions in runtime ones to avoid repetitive throws declarations.
public void setLong(PreparedStatement stmt, int idx, Long val) throws SQLException {
if (val != null) {
stmt.setLong(idx, val);
} else {
stmt.setNull(idx, Types.BIGINT);
}
}10. Annotation Shortcuts
Use Lombok to generate boilerplate, Validation for constraints, and @NonNull to express required parameters.
@Getter @Setter @ToString
public class UserVO {
private Long id;
private String name;
}11. Generic Techniques
Introduce type parameters to eliminate duplicated code for different data types.
public interface Comparable<T> {
int compareTo(T other);
}
public class Point<T extends Number> {
private T x;
private T y;
}12. Constructor Overloads
Use @AllArgsConstructor and @NoArgsConstructor to create objects in a single line.
return new PageDataVO<>(totalCount, userList);13. Set add Return Value
Use the boolean result of Set.add to replace a separate contains check.
if (userIdSet.add(userDO.getId())) {
userVOList.add(transUser(userDO));
}14. Map computeIfAbsent
Replace manual map‑initialisation with computeIfAbsent.
roleUserMap.computeIfAbsent(userDO.getRoleId(), k -> new ArrayList<>())
.add(userDO);15. Chain Calls
Build objects via method chaining for fluent APIs.
StringBuilder sb = new StringBuilder(96)
.append("select id, name from ")
.append(T_USER)
.append(" where id = ")
.append(userId)
.append(";");16. Array‑Based Simplifications
Use IntStream to generate numeric sequences.
int[] range = IntStream.rangeClosed(1, N).toArray();
int[] powers = IntStream.iterate(1, n -> n * 2).limit(N).toArray();17. Data‑Structure Helpers
Employ ThreadLocal for per‑thread objects, Optional for null‑safe handling, and container classes like Pair or Triple to return multiple values.
ThreadLocal<DateFormat> fmt = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
String dateStr = fmt.get().format(date);18. Optional Usage
Replace explicit null checks with Optional pipelines.
Integer thisValue = Optional.ofNullable(value).orElse(DEFAULT_VALUE);
String zip = Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCountry)
.map(Country::getZipcode)
.orElse(null);19. Stream API Patterns
Common stream patterns for matching, filtering, aggregation, mapping, grouping, and range generation.
// Match
boolean found = userList.stream().anyMatch(u -> Objects.equals(u.getId(), userId));
// Filter
List<UserDO> superUsers = userList.stream()
.filter(u -> Boolean.TRUE.equals(u.getIsSuper()))
.collect(Collectors.toList());
// Sum
double total = accountList.stream().mapToDouble(Account::getBalance).sum();
// Map conversion
List<UserVO> voList = userDOList.stream()
.map(this::transUser)
.collect(Collectors.toList());
// Grouping
Map<Long, List<UserDO>> byRole = userDOList.stream()
.collect(Collectors.groupingBy(UserDO::getRoleId));
// Group‑and‑sum
Map<Long, Double> roleTotal = accountList.stream()
.collect(Collectors.groupingBy(Account::getRoleId, Collectors.summingDouble(Account::getBalance)));
// Range generation
int[] nums = IntStream.rangeClosed(1, N).toArray();20. Program‑Structure Clean‑ups
Return boolean expressions directly, minimise the scope of conditionals, and place expressions where they reduce duplication.
public boolean isSuper(Long userId) {
UserDO user = userDAO.get(userId);
return Objects.nonNull(user) && Boolean.TRUE.equals(user.getIsSuper());
}
String message = result.isSuccess() ? "上报工作日报成功" : "上报工作日报失败:" + result.getMessage();
log.warn(message);
dingtalkService.sendMessage(user.getPhone(), message);21. Design‑Pattern Refactorings
Apply the Template Method pattern to share Redis key handling, replace verbose builder interfaces with functional parameters, and use @ControllerAdvice or AOP for centralized exception handling.
// Template method example
public abstract class AbstractDynamicValue<I, V> {
@Resource(name="stringRedisTemplate")
private ValueOperations<String, String> ops;
public void set(I id, V val) { ops.set(key(id), JSON.toJSONString(val)); }
public V get(I id) { return JSON.parseObject(ops.get(key(id)), valueClass()); }
protected abstract String key(I id);
protected abstract Class<V> valueClass();
}22. Aggressive Dead‑Code Removal
Delete unused imports, redundant public modifiers in interfaces, unnecessary private on enum constructors, final on methods of final classes, superfluous implements clauses, and variables that merely forward a call.
// Before
public interface UserDAO { public Long countUser(...); }
// After
public interface UserDAO { Long countUser(...); }The above collection of shortcuts and refactorings enables Java developers to write more concise, maintainable, and performant backend code.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
