[Java-11] 컬렉션 프레임웍 - Arrays, Comparator, Comparable, HashSet, TreeSet
1. Arrays
- 배열을 다루는데 유용한 메서드가 정의되어 있음
1) 배열의 복사 copyOf(), copyOfRange()
- copyOf() : 배열 전체를 복사하여 새로운 배열을 반환
- copyOfRange() : 배열의 일부를 복사하여 새로운 배열을 반환 (지정된 범위의 끝은 포함 X)
int[] arr = {0,1,2,3,4};
int[] arr2 = Arrays.copyOf(arr, arr.length); // 0,1,2,3,4
int[] arr3 = Arrays.copyOf(arr, 3); // 0,1,2
int[] arr4 = Arrays.copyOf(arr, 7); // 0,1,2,3,4,0,0
int[] arr5 = Arrays.copyOfRange(arr, 2, 4); // 2,3
2) 배열 채우기 fill(), setAll()
- fill() : 배열의 모든 요소를 지정된 값으로 채움
- setAll() : 배열을 체우는데 사용할 함수형 인터페이스를 매개변수로 받음
(함수형 인터페이스를 구현한 객체를 매개변수로 지정하던가 람다식을 지정해야 함)
int[] arr = new int[5];
Arrays.fill(arr, 9); // arr = {9,9,9,9,9}
Arrays.setAll(arr, () -> (int)(Math.random()*5)+1); // arr = {1,5,2,1,1}
3) 배열의 정렬과 검색 sort(), binarySearch()
- sort() : 배열을 정렬
- binarySearch() : 배열에 저장된 요소를 검색 (반드시 배열이 정렬된 상태이어야 올바른 결과를 얻음)
int[] arr = {3, 2, 1, 4, 0};
int idx = Arrays.binarySearch(arr, 2); // 잘못된 결과가 나옴
Arrays.sort(arr); // arr = {0, 1, 2, 3, 4}
int idx2 = Arrays.binarySearch(arr, 2); // idx2 = 2
4) 배열의 비교와 출력 equals(), toString()
- toString() : 모든 요소를 문자열로 출력 (일차원 배열만 가능)
- deepToString() : 모든 요소를 문자열로 출력 (다차원 배열도 가능)
-> 모든 요소를 재귀적으로 접근하여 문자열을 구성하므로 다차원 배열도 가능함
int[] arr = {0,1,2,3,4};
int[][] arr2D = {{11,22}, {21,22}};
System.out.println(Array.toString(arr)); // [0, 1, 2, 3, 4]
System.out.println(Array.deepToString(arr2D)); // [[11, 12], [21, 22]]
- equals() : 두 배열에 저장된 모든 요소를 비교 (같으면 true 다르면 false 반환, 일차원 배열만 가능)
- deepEquals() : 두 배열에 저장된 모든 요소를 비교 (같으면 true 다르면 false 반환, 다차원 배열도 가능)
String[][] str2D = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};
String[][] str2D2 = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};
System.out.println(Arrays.equals(str2D, str2D2)); // false
System.out.println(Arrays.deepEquals(str2D, str2D2)); // true
5) 배열을 List로 변환 asList(Object... a)
- asList() : 배열을 List에 담아서 반환
- 매개변수의 타입이 가변인수라서 배열 생성없이 저장할 요소들만 나열하는 것도 가능
List list = Arrays.asList(new Integer[]{1,2,3,4,5}); // list = [1,2,3,4,5]
List list2 = Arrays.asList(1,2,3,4,5); // list2 = [1,2,3,4,5]
list.add(6); // UnsupportedOperationException 예외 발생
- 단, asList()가 반환한 배열의 크기는 변경할 수 없음
- 다음과 같이 하면 크기를 변경할 수 있음
List list = new ArrayList(Arrays.asList(1,2,3,4,5));
6) 그 외 메소드
- parallelXXX() : 빠른 결과를 얻기 위해 여러 쓰레드가 작업을 나누어 처리하도록 함
- spliterator() : 여러 쓰레드가 처리할 수 있게 하나의 작업을 여러 작업으로 나누는 Spliterator를 반환
- stream() : 컬렉션을 스트림으로 변환
2. Comparator, Comparable
1) Comparator와 Comparable의 기능
- Comparator와 Comparable 모두 인터페이스로 컬렉션을 정렬하는데 필요한 메서드를 정의하고 있음
- Comparable을 구현하고 있는 클래스들은 같은 타입의 인스턴스끼리 서로 비교할 수 있는 클래스들임
(주로, Integer와 같은 wrapper클래스, String, Date, File 등)
- 기본적으로 오름차순으로 정렬되도록 구현되어 있음
- Comparable을 구현한 클래스 = 정렬이 가능함
2) Comparator와 Comparable의 실제 소스
public interface Comparator {
int compare(Object o1, Object o2);
boolean equals(Object obj);
}
public interface Comparable {
public int compareTo(Object o);
}
- compare()와 compareTo()는 같은 기능
- 반환값은 int지만, 실제로 비교하는 두 객체가 같으면 0, 비교하는 값보다 작으면 음수, 크면 양수를 반환하도록 구현해야 함
3) Comparator와 Comparable의 차이
Comparator : 기본 정렬기준(오름차순) 외에 다른 기준으로 정렬하고자할 때 사용
Comparable : 기본 정렬기준(오름차순)을 구현하는데 사용
4) 사용 예시
class Ex {
public static void main(String[] args) {
String[] arr = {"cat", "Dog", "lion", "tiger"};
// 1. 기본 정렬
Array.sort(strArr); // Dog, cat, lion, tiger
// 2. 기본 정렬 + 대소문자 구분 X
Array.sort(strArr, String.CASE_INSENSITIVE_ORDER); // cat, Dog, lion, tiger
// 3. 역순 정렬
Array.sort(strArr, new Descending()); // tiger, lion, cat, Dog
}
}
class Descending implements Comparator {
public int compare(Object o1, Object o2) {
if(o1 instanceof Comparable && o2 instanceof Comparable) {
Comparable c1 = (Comparable)o1;
Comparable c2 = (Comparable)o2;
return c1.compareTo(c2) * -1; // -1을 곱하여 정렬방식의 역(내림차순)으로 변경
}
}
}
- Arrays.sort(Object[] a) : 객체 배열에 저장된 객체가 구현한 Comparable에 의한 정렬
- Arrays.sort(Object[] a, Comparator c) : 지정한 Comparable에 의한 정렬
- String.CASE_INSENSITIVE_ORDER) : 문자열을 대소문자 구분없이 정렬할 수 있음
3. HashSet
- Set인터페이스를 구현한 가장 대표적인 컬렉션
- Set인터페이스의 특징에 따라 저장순서를 유지하지 않고 중복된 요소를 저장하지 않음
- 저장순서를 유지하고 싶으면 LinkedHashSet을 사용해야 함
1) 생성자
HashSet() | HashSet객체를 생성함 |
HashSet(Collection c) | 주어진 컬렉션을 포함하는 HashSet객체를 생성 |
HashSet(int initialCapactiy) | 주어진 값을 초기용량으로 하는 HashSet객체를 생성 |
HashSet(int initialCapacity, float loadFator) | 초기용량과 load factor를 지정하는 생성자 (load factor : 컬렉션 클래스의 저장공간이 가득 차기 전에 미리 용량을 확보하기 위한 것) |
2) 데이터 추가
boolean add(Object o) | 새로운 객체를 저장 |
boolean addAll(Collection c) | 주어진 컬렉션에 저장된 모든 객체들을 추가함 (합집합) |
- HashSet에 이미 같은 객체가 존재할 경우 중복으로 간주하고 저장하지 않으며 작업이 실패했다는 의미로 false를 반환함
3) 데이터 삭제
boolean remove(Object o) | 지정된 객체를 삭제 (성공하면 true, 실패하면 false 반환) |
boolean removeAll(Collection c) | 주어진 컬렉션에 저장된 모든 객체와 동일한 것들을 HashSet에서 모두 삭제 (차집합) |
boolean retainAll(Collection c) | 주어진 컬렉션에 저장된 객체와 동일한 것만 남기고 삭제 (교집합) |
4) 기타
void clear() | 저장된 모든 객체 삭제 |
Object clone() | HashSet을 복제해서 반환 (얕은 복사) |
boolean contains(Object o) | 지정된 객체를 포함하고 있는지 알려줌 |
boolean containsAll(Collection c) | 주어진 컬렉션에 저장된 모든 객체들을 포함하고 있는지 알려줌 |
boolean isEmpty() | 비어있는지 알려줌 |
Iterator iterator() | Iterator를 반환함 |
int size() | 저장된 객체의 개수 반환 |
Object[] toArray() | 저장된 객체들을 객체배열의 형태로 반환 |
Object[] toArray(Object[] a) | 저장된 객체들을 주어진 객체배열(a)에 담음 |
4. TreeSet
- 이진 검색 트리라는 자료구조의 형태로 데이터를 저장하는 컬렉션 클래스
- 이진 검색 트리(binary search tree) : 정렬, 검색, 범위검색(range search)에 높은 성능을 보이는 자료구조
- TreeSet은 이진 검색 트리의 성능을 향상시킨 '레드-블랙 트리(Red-Black tree)'로 구현됨
- Set인터페이스를 구현했으므로 저장순서를 유지하지 않고 중복을 허용하지 않음
1) 이진 검색 트리(binary search tree)
- LinkedList처럼 여러 개의 노드(node)가 서로 연결된 구조
- 각 노드에 최대 2개의 노드를 연결할 수 있음
- '루트(root)'라고 불리는 하나의 노드에서부터 시작해서 계속 확장해나갈 수 있음
- 왼쪽 자식노드의 값은 부모노드의 값보다 작고 오른쪽 자식노드의 값은 부모노드의 값보다 커야함
- 노드의 추가 삭제에 시간이 걸림 (순차적으로 저장하지 않으므로)
- 검색(범위검색)과 정렬에 유리함
- 중복된 값을 저장하지 못함
2) 생성자
TreeSet() | TreeSet을 생성 |
TreeSet(Collection c) | 주어진 컬렉션을 저장하는 TreeSet을 생성 |
TreeSet(Comparator comp) | 주어진 정렬조건으로 정렬하는 TreeSet을 생성 |
TreeSet(SortedSet s) | 주어진 SortedSet을 구현한 컬렉션을 저장하는 TreeSet을 생성 |
3) 데이터 추가
boolean add(Object o) | 새로운 객체를 저장 |
boolean addAll(Collection c) | 주어진 컬렉션에 저장된 모든 객체들을 추가함 |
4) 데이터 삭제
boolean remove(Object o) | 지정된 객체를 삭제 (성공하면 true, 실패하면 false 반환) |
boolean retainAll(Collection c) | 주어진 컬렉션에 저장된 객체와 동일한 것만 남기고 삭제 (교집합) |
5) 검색
Object ceiling(Object o) | 지정된 객체와 같은 객체를 반환 없으면 큰 값을 가진 객체 중 제일 가까운 값의 객체를 반환 없으면 null |
Object floor(Object o) | 지정된 객체와 같은 객체를 반환 없으면 작은 값을 가진 객체 중 제일 가까운 값의 객체를 반환 없으면 null |
boolean contains(Object o) boolean containsAll(Collection c) |
지정된 객체(o) 또는 컬렉션들의 객체들이 포함되어 있는지 확인 |
Object first() | 정렬된 순서에서 첫 번째 객체 반환 |
Object last() | 정렬된 순서에서 마지막 객체 반환 |
Object higher(Object o) | 지정된 객체보다 큰 값을 가진 객체 중 제일 가까운 값의 객체 반환 없으면 null |
Object lower(Object o) | 지정된 객체보다 작은 값을 가진 객체 중 제일 가까운 값의 객체 반환 없으면 null |
Object pollFirst() | TreeSet의 첫번째 요소(제일 작은 값의 객체)를 반환 |
Object pollLast() | TreeSet의 마지막 요소(제일 큰 값의 객체)를 반환 |
SortedSet headSet(Object toElement) | 지정된 객체보다 작은 값의 객체들을 반환 |
NavigableSet headSet(Object toElement, boolean inclusive) | 지정된 객체보다 작은 값의 객체들을 반환 inclusive가 true이면, 같은 값의 객체도 포함 |
SortedSet tailSet(Object fromElement) | 지정된 객체보다 큰 값의 객체들을 반환 |
SortedSet subSet(Object fromElement, Object toElement) | 범위 검색 (fromElement와 toElement 사이)의 결과를 반환 (fromElement는 포함X) |
NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) | 범위 검색 (fromElement와 toElement 사이)의 결과를 반환 (fromInclusive가 true면 시작값이 포함, toInclusive가 true면 끝 값이 포함) |
6) 기타
void clear() | 저장된 모든 객체 삭제 |
Object clone() | TreeSet을 복제해서 반환 |
Comparator comparator() | TreeSet의 정렬기준(Comparator)을 반환 |
boolean isEmpty() | 비어있는지 알려줌 |
Iterator iterator() | Iterator를 반환함 |
Spliterator spliterator() | TreeSet의 spliterator 반환 |
int size() | 저장된 객체의 개수 반환 |
Object[] toArray() | 저장된 객체들을 객체배열의 형태로 반환 |
Object[] toArray(Object[] a) | 저장된 객체들을 주어진 객체배열(a)에 담음 |
참고 - Java의 정석 3rd Edition (저자 : 남궁성, 출판 : 도우출판)