빠른 비교
users.sort(Comparator
.comparing(User::getAge)
.thenComparing(User::getName));
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}갈리는 기준
어떤 순회와 정렬 형태를 먼저 떠올리면 되나
| 상황 | 먼저 떠올릴 선택 |
|---|---|
| 읽기 전용 순회 | for-each |
| 순회 중 안전하게 제거 | Iterator.remove() |
| Map의 key와 value를 같이 순회 | entrySet() |
| 클래스의 기본 정렬 규칙 | Comparable |
| 화면/상황별 다른 정렬 기준 | Comparator |
순회 방식 선택
for-each는 읽기 전용 순회에 가장 자연스럽습니다. Iterator는 순회 중 원소를 제거할 때(ConcurrentModificationException 방지) 필요합니다. Map 순회는 key만 필요하면 keySet(), value만 필요하면 values(), 둘 다 필요하면 entrySet()을 씁니다.
// Map 순회 시 entrySet()이 가장 효율적 (key로 get()을 다시 호출하지 않음)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 순회 중 제거가 필요할 때 Iterator 사용
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().startsWith("X")) {
it.remove(); // ConcurrentModificationException 없이 안전하게 제거
}
}Comparable vs Comparator 선택 기준
Comparable은 클래스의 "기본 정렬 기준"을 클래스 안에 넣는 방식입니다. TreeSet, Collections.sort() 등에서 자동으로 사용됩니다. Comparator는 상황에 따라 정렬 기준이 바뀔 때 외부에서 주입합니다.
// Comparable: ID 오름차순이 기본 순서
class User implements Comparable<User> {
@Override
public int compareTo(User other) {
return Long.compare(this.id, other.id);
}
}
// Comparator: 화면 표시용 이름 정렬 등 상황별 다른 기준
users.sort(Comparator.comparing(User::getName));
users.sort(Comparator.comparing(User::getAge).reversed());조합형 Comparator API
현대 Java의 Comparator.comparing, thenComparing, reversed, nullsFirst, nullsLast 덕분에 정렬 로직을 선언적으로 조합할 수 있습니다.
users.sort(Comparator
.comparing(User::getDepartment)
.thenComparing(User::getAge)
.thenComparing(Comparator.comparing(User::getName).reversed()));선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 단순 읽기 순회 | for-each |
| 순회 중 원소 제거 | Iterator.remove() |
| Map key+value 함께 순회 | entrySet() |
| 클래스의 기본 정렬 순서 | Comparable 구현 |
| 상황별 다른 정렬 전략 | Comparator 주입 |
주의할 점
for-each 순회 중에 list.remove()를 직접 호출하면 ConcurrentModificationException이 발생합니다.
// ❌ for-each 중 직접 remove
for (String item : list) {
if (item.startsWith("X")) {
list.remove(item); // ConcurrentModificationException!
}
}
// ✅ Iterator 사용
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().startsWith("X")) it.remove();
}
// ✅ 또는 Stream + filter로 새 리스트 생성
list = list.stream().filter(s -> !s.startsWith("X")).toList();참고 링크
3 sources