Java 代码优化技巧:场景与实践
Java 代码优化技巧:场景与实践
Java 代码优化是提高应用性能、减少资源消耗并增强可维护性的关键实践。以下是针对不同场景的详细优化技巧。
1. 性能优化场景
场景 1.1:循环优化
优化前:
public void processLargeList(List<String> items) {
for (int i = 0; i < items.size(); i++) {
String item = items.get(i);
// 处理每个元素
processItem(item);
}
}
优化后:
public void processLargeList(List<String> items) {
// 预先获取集合大小,避免重复调用 size() 方法
int size = items.size();
// 对于 ArrayList,使用索引遍历更高效
if (items instanceof ArrayList) {
for (int i = 0; i < size; i++) {
processItem(items.get(i));
}
} else {
// 对于 LinkedList 等其他集合,使用迭代器更高效
for (String item : items) {
processItem(item);
}
}
}
优化说明:
- 避免在循环条件中重复调用
size()
- 根据集合类型选择最优的遍历方式
- 对于 ArrayList,索引访问是 O(1) 操作
- 对于 LinkedList,迭代器遍历避免了 O(n) 的索引查找
场景 1.2:字符串连接优化
优化前:
public String buildReport(List<String> data) {
String result = "";
for (String item : data) {
result += item + ", ";
}
return result;
}
优化后:
public String buildReport(List<String> data) {
// 预估容量,减少扩容操作
StringBuilder sb = new StringBuilder(data.size() * 20);
for (int i = 0; i < data.size(); i++) {
sb.append(data.get(i));
if (i < data.size() - 1) {
sb.append(", ");
}
}
return sb.toString();
}
优化说明:
- 使用 StringBuilder 代替字符串连接操作
- 预估 StringBuilder 初始容量,减少扩容次数
- 避免在循环中创建临时字符串对象
- 条件判断避免末尾多余的分隔符
场景 1.3:并行处理大数据集
优化前:
public List<Integer> processNumbers(List<Integer> numbers) {
List<Integer> results = new ArrayList<>(numbers.size());
for (Integer number : numbers) {
results.add(expensiveOperation(number));
}
return results;
}
优化后:
public List<Integer> processNumbers(List<Integer> numbers) {
return numbers.parallelStream()
.map(this::expensiveOperation)
.collect(Collectors.toList());
}
优化说明:
- 利用 Java 8 的并行流处理大数据集
- 自动利用多核 CPU 资源
- 适用于计算密集型且独立的操作
- 减少了手动线程管理的复杂性
2. 内存优化场景
场景 2.1:对象池复用
优化前:
public class DatabaseProcessor {
public void processBatch(List<Record> records) {
for (Record record : records) {
Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
try {
processRecord(conn, record);
} finally {
conn.close();
}
}
}
}
优化后:
public class DatabaseProcessor {
private final DataSource connectionPool;
public DatabaseProcessor() {
// 初始化连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl(DB_URL);
config.setUsername(USER);
config.setPassword(PASS);
config.setMaximumPoolSize(10);
connectionPool = new HikariDataSource(config);
}
public void processBatch(List<Record> records) {
for (Record record : records) {
try (Connection conn = connectionPool.getConnection()) {
processRecord(conn, record);
} catch (SQLException e) {
logger.error("处理记录失败", e);
}
}
}
}
优化说明:
- 使用连接池复用数据库连接
- 避免频繁创建和销毁连接的开销
- 使用 try-with-resources 确保资源正确关闭
- 限制最大连接数,防止资源耗尽
场景 2.2:减少装箱拆箱操作
优化前:
public int sumValues(List<Integer> values) {
int sum = 0;
for (Integer value : values) {
sum += value; // 自动拆箱
}
return sum;
}
优化后:
public int sumValues(List<Integer> values) {
// 使用基本类型流避免拆箱
return values.stream()
.mapToInt(Integer::intValue)
.sum();
// 或者手动拆箱
/*
int sum = 0;
for (int i = 0; i < values.size(); i++) {
sum += values.get(i).intValue();
}
return sum;
*/
}
优化说明:
- 使用专门的基本类型流 (IntStream) 避免装箱拆箱
- 对于性能关键代码,考虑手动拆箱
- 减少了创建临时对象的开销
- 降低了垃圾回收压力
场景 2.3:使用软引用缓存大对象
优化前:
public class ImageProcessor {
private Map<String, BufferedImage> imageCache = new HashMap<>();
public BufferedImage getImage(String path) {
if (imageCache.