Optimizing Nested Loops in Java: Using break and HashMap for Significant Performance Gains
This article analyzes a common Java scenario of nested for‑loops over large user and user‑memo lists, demonstrates the performance impact of adding a break statement, and shows how converting the inner list to a HashMap can reduce execution time from tens of seconds to a few seconds.
In many Java code reviews, developers write nested for‑loops to match items from two large collections, such as a List<User> and a List<UserMemo>, which leads to poor performance.
Scenario example: For each User we need to find the corresponding UserMemo by userId and process its content.
Data size used for the demonstration: 50,000 User objects and 30,000 UserMemo objects.
Initial implementation (nested loops without break):
import lombok.Data;
@Data
public class User {
private Long userId;
private String name;
}
import lombok.Data;
@Data
public class UserMemo {
private Long userId;
private String content;
}
public static List<User> getUserTestList() {
List<User> users = new ArrayList<>();
for (int i = 1; i <= 50000; i++) {
User user = new User();
user.setName(UUID.randomUUID().toString());
user.setUserId((long) i);
users.add(user);
}
return users;
}
public static List<UserMemo> getUserMemoTestList() {
List<UserMemo> userMemos = new ArrayList<>();
for (int i = 30000; i >= 1; i--) {
UserMemo userMemo = new UserMemo();
userMemo.setContent(UUID.randomUUID().toString());
userMemo.setUserId((long) i);
userMemos.add(userMemo);
}
return userMemos;
}
public static void main(String[] args) {
List<User> userTestList = getUserTestList();
List<UserMemo> userMemoTestList = getUserMemoTestList();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (User user : userTestList) {
Long userId = user.getUserId();
for (UserMemo userMemo : userMemoTestList) {
if (userId.equals(userMemo.getUserId())) {
String content = userMemo.getContent();
System.out.println("模拟数据content 业务处理......" + content);
}
}
}
stopWatch.stop();
System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());
}The above code iterates 5 × 10⁴ × 3 × 10⁴ ≈ 1.5 billion comparisons, taking about 26,857 ms on the test machine.
Optimization 1 – add break after a match is found:
public static void main(String[] args) {
List<User> userTestList = getUserTestList();
List<UserMemo> userMemoTestList = getUserMemoTestList();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (User user : userTestList) {
Long userId = user.getUserId();
for (UserMemo userMemo : userMemoTestList) {
if (userId.equals(userMemo.getUserId())) {
String content = userMemo.getContent();
System.out.println("模拟数据content 业务处理......" + content);
break;
}
}
}
stopWatch.stop();
System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());
}With the break, execution time drops to roughly 10‑12 seconds, roughly halving the cost.
Optimization 2 – replace the inner loop with a HashMap lookup:
public static void main(String[] args) {
List<User> userTestList = getUserTestList();
List<UserMemo> userMemoTestList = getUserMemoTestList();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Map<Long, String> contentMap =
userMemoTestList.stream().collect(Collectors.toMap(UserMemo::getUserId, UserMemo::getContent));
for (User user : userTestList) {
Long userId = user.getUserId();
String content = contentMap.get(userId);
if (StringUtils.hasLength(content)) {
System.out.println("模拟数据content 业务处理......" + content);
}
}
stopWatch.stop();
System.out.println("最终耗时" + stopWatch.getTotalTimeMillis());
}Using a map reduces the time complexity from O(N·M) to O(N+M); the measured execution time falls to about 2‑3 seconds, a dramatic improvement.
The article also includes a snippet of the JDK 8 HashMap.getNode implementation to illustrate why hash‑based lookups are near O(1) under normal conditions, and notes that only a pathological scenario where all keys collide would degrade performance to O(N).
Overall, the piece teaches backend developers how a simple break and a proper use of HashMap can turn a costly nested iteration into an efficient linear‑time operation.
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.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.
