공부/Java

[Java-11] 컬렉션 프레임웍 - Arrays, Comparator, Comparable, HashSet, TreeSet

줭♪(´▽`) 2021. 4. 15. 18:31

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 (저자 : 남궁성, 출판 : 도우출판)