Java 컬렉션 알고리즘 마스터하기: 정렬, 셔플링 등
Java 알고리즘
이 튜토리얼에서는 명확하고 실습 위주의 예제를 통해 Java Collections Framework가 제공하는 강력한 알고리즘들을 탐구합니다.
Java Collections Framework는 일반 알고리즘(generic algorithms)이라 불리는 풍부한 정적 메서드 세트를 제공하여, 반복적인 코드 작성 없이 자료구조를 조작할 수 있게 합니다. 이 유틸리티들은 Collection 인터페이스를 구현하는 모든 컬렉션과 호환되며, 단순함과 성능을 모두 제공합니다.
아래에서 가장 자주 사용되는 알고리즘들을 문법, 동작 방식, 실용적 활용 사례와 함께 살펴보겠습니다.
1. Collections.sort()로 정렬하기
sort() 메서드는 요소를 자연 순서(오름차순)로 정렬합니다. 커스텀 정렬이 필요하다면 Comparator 구현을 제공하면 됩니다.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(4);
numbers.add(2);
numbers.add(3);
System.out.println("Unsorted ArrayList: " + numbers);
Collections.sort(numbers);
System.out.println("Sorted ArrayList: " + numbers);
}
}
실행 결과
Unsorted ArrayList: [4, 2, 3]
Sorted ArrayList: [2, 3, 4]
내림차순이나 도메인별 기준이 필요하다면 커스텀 Comparator를 사용하세요. 자세한 내용은 Java 정렬 가이드를 참조하세요.
2. Collections.shuffle()로 순서 무작위화
게임이나 샘플링 시나리오에 적합하게 요소 순서를 무작위로 섞으려면 shuffle()을 사용하세요.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("Sorted ArrayList: " + numbers);
Collections.shuffle(numbers);
System.out.println("ArrayList after shuffle: " + numbers);
}
}
실행 결과
Sorted ArrayList: [1, 2, 3]
ArrayList after shuffle: [2, 1, 3]
내부적으로 Fisher-Yates 알고리즘을 사용하므로 실행할 때마다 다른 순열이 생성됩니다.
3. 루틴 데이터 조작
Java는 컬렉션을 변환하기 위한 다양한 유틸리티 메서드를 제공합니다:
reverse() - 요소 순서를 뒤집습니다.
fill() - 모든 요소를 지정된 값으로 대체합니다.
copy() - 한 컬렉션의 요소를 다른 컬렉션으로 복사합니다(크기가 같아야 함).
swap() - 인덱스로 두 요소를 교환합니다.
addAll() - 한 컬렉션의 모든 요소를 다른 컬렉션에 추가합니다.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
System.out.println("ArrayList1: " + numbers);
Collections.reverse(numbers);
System.out.println("Reversed ArrayList1: " + numbers);
Collections.swap(numbers, 0, 1);
System.out.println("ArrayList1 after swap(): " + numbers);
ArrayList<Integer> newNumbers = new ArrayList<>();
newNumbers.addAll(numbers);
System.out.println("ArrayList2 using addAll(): " + newNumbers);
Collections.fill(numbers, 0);
System.out.println("ArrayList1 after fill(): " + numbers);
Collections.copy(newNumbers, numbers);
System.out.println("ArrayList2 after copy(): " + newNumbers);
}
}
실행 결과
ArrayList1: [1, 2]
Reversed ArrayList1: [2, 1]
ArrayList1 after swap(): [1, 2]
ArrayList2 using addAll(): [1, 2]
ArrayList1 after fill(): [0, 0]
ArrayList2 after copy(): [0, 0]
참고: copy() 메서드는 대상 컬렉션이 소스만큼의 요소를 가지고 있어야 합니다.
4. Collections.binarySearch()로 이진 검색
정렬된 컬렉션에서 요소를 효율적으로 찾습니다. 메서드는 요소의 인덱스를 반환하거나, 없으면 음수 삽입 지점을 반환합니다.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
int pos = Collections.binarySearch(numbers, 3);
System.out.println("The position of 3 is " + pos);
}
}
실행 결과
The position of 3 is 2.
팁: binarySearch()를 호출하기 전에 항상 컬렉션을 정렬하세요. 그렇지 않으면 결과가 정의되지 않습니다.
더 자세한 내용은 Java 이진 검색 문서를 참조하세요.
5. 컬렉션 구성 분석
이 유틸리티들은 컬렉션 간의 관계를 분석합니다:
frequency() - 특정 요소의 발생 횟수를 셉니다.
disjoint() - 두 컬렉션이 공통 요소를 공유하지 않는지 확인합니다.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(2);
System.out.println("ArrayList1: " + numbers);
int count = Collections.frequency(numbers, 2);
System.out.println("Count of 2: " + count);
ArrayList<Integer> newNumbers = new ArrayList<>();
newNumbers.add(5);
newNumbers.add(6);
System.out.println("ArrayList2: " + newNumbers);
boolean disjoint = Collections.disjoint(numbers, newNumbers);
System.out.println("Two lists are disjoint: " + disjoint);
}
}
실행 결과
ArrayList1: [1, 2, 3, 2]
Count of 2: 2
ArrayList2: [5, 6]
Two lists are disjoint: true
6. 최솟값과 최댓값 찾기
min()과 max()로 가장 작은 요소나 가장 큰 요소를 조회하세요. 분석과 경계 확인에 유용합니다.
import java.util.ArrayList;
import java.util.Collections;
class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
int min = Collections.min(numbers);
System.out.println("Minimum Element: " + min);
int max = Collections.max(numbers);
System.out.println("Maximum Element: " + max);
}
}
실행 결과
Minimum Element: 1
Maximum Element: 3