컬렉션 모든 함수를 외우지는 말고 필요한 함수를 그 때 그 때 찾아서 사용하면 된다.
- 컬렉션 (Collection)
- 자료구조
- 배열의 문제점과 컬렉션 장점
- 컬렉션 주요 인터페이스
- 컬렉션 요소 접근 인터페이스
- List
- Set
- Map
- TreeSet 과 TreeMap 정렬
메모리상에서 자료를 구조적으로 처리하는 방법을 자료구조라 일컫는데
컬렉션은 자바에서 제공하는 자료구조를 담당하는 프레임워크이다.
추가와 삭제와 정렬 등의 기능처리가 간단하게 해결 되어 자료구조적 알고리즘을 구현할 필요가 없다.
java.util
패키지에 포함되며 인터페이스를 통해 정형화된 방법으로 다양한 컬렉션 클래스 이용이 가능하다.
데이터를 메모리에서 구조적으로 처리하는 방법론이다.
Wrapper
클래스를 사용한다.가장 중요하고 많이 사용되는 것은 Map 이다.
List
와 Set
은 코드를 추상화 한 것이고 Map
은 코드가 다르기 때문에 추상화 하지 않았다.
List
는 배열이라고 볼 수 있고 Set
은 주머니 또는 집합이라고 보면 된다. Map
은 Key 값과 Value 쌍을 저장하고 있다고 볼 수 있다.
컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스이다. Iterator
은 반복자라는 뜻을 가지고 있으며 코드 설명에 Iterator
가 있으면 순차적으로 반복 접근이 가능하다.
Iterator<String> it = set.iterator();
while (it.hasNext()) { // 다음 객체가 존재하면 true 아니면 false
String temp = it.next(); // 다음 객체를 꺼내옴
System.out.println(temp);
}
List 와 Set 만 Iterator 을 상속받고 있기 때문에 두 계열에서만 iterator ( ) 메서드 사용이 가능하다.
Map 의 경우 Set 또는 List 화 시켜서 메서드를 사용해야 한다.
자료들을 순차적으로 나열한 자료구조로 인덱스로 관리되며 중복해서 객체 저장이 가능한 배열이라고 볼 수 있다. 구현 클래스로 ArrayList
와 Vector
및 LinkedList
가 있다.
List 계열 주요 메서드는 다음과 같다. 아래에서 E 는 Element 의 약자로 요소 즉 객체를 의미하는 제네릭 표기법이며 Object 타입으로 생각하면 된다.
set 메서드의 경우 index 에 위치하는 요소를 element 로 변경하는 기능과 기존에 있던 요소를 반환하는 기능 두 가지를 가지고 있다.
List 의 후손으로 초기 저장 용량은 10 으로 자동 설정되며 따로 지정도 가능하다.
저장 용량을 초과한 객체들이 들어오면 자동으로 늘어나며 고정도 가능하고 동기화를 제공하지 않는다.
List<E> list = new ArrayList<E>();
동기화
란 하나의 자원 즉 데이터에 대해 여러 스레드가 접근 하려 할 때 한 시점에서 하나의 스레드만 사용할 수 있도록 하는 것이다.
List 의 후손으로 ArrayList 와 동등하지만 동기화를 제공한다는 점 때문에 List 객체들 중에서 가장 성능이 좋지 않다.
List 의 후손으로 인접 참조를 링크해 체인처럼 관리한다. 특정 인덱스에서 객체를 제거하거나 추가하게 되면 바로 앞뒤 링크만 변경하면 되기 때문에 객체 삭제와 삽입이 빈번하게 일어나는 곳에서는 ArrayList 보다 성능이 좋다.
저장 순서가 유지되지 않고 중복 객체도 저장하지 못하게 하는 자료 구조이다.
null 도 중복을 허용하지 않기 때문에 한 개의 null 만 저장한다.
만약 중복값이 들어오면 같은 객체를 덮어 씌운다.
구현 클래스로 HashSet
과 LinkedHashSet
및 TreeSet
이 있다.
추가로 Hash 가 붙은 Set 이나 Map 은 hashCode ( ) 를 이용해서 중복을 판단하므로 이들을 사용하려면 equals ( ) 와 hashCode ( ) 오버라이딩이 필수이다.
Set 계열 주요 메서드는 다음과 같으며 List 계열 주요 메서드와 동일하다.
Set 에 객체를 저장할 때 hash 함수를 사용하여 처리 속도가 빠르다.
HashSet 은 동일 객체 뿐만 아니라 동등 객체도 중복해서 저장하지 않는다.
HashSet 과 거의 동일하지만 Set 에 추가되는 순서를 유지한다는 점이 다르다.
TreeSet 은 이진 트리를 기반으로 한 검색 기능을 강화시킨 Set 컬렉션으로 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수로 구성된다.
key 와 value 로 구성되어 있으며 키와 값은 모두 객체이다.
키는 중복 저장을 허용하지 않는 Set 방식이며 값은 중복 저장을 허용하는 List 방식이다.
키가 중복되는 경우 기존에 있는 키에 해당하는 값을 덮어 씌운다.
Map 은 한 번에 다량의 데이터를 전달해야하는 경우와 데이터의 명확한 구분이 필요한 경우에 유용하다. 또한 재사용성이 적은 DTO 를 대체하는 경우나 별도의 DTO 가 없을 경우 사용하면 좋다.
Map 계열 주요 메서드는 다음과 같다.
키 객체는 hashCode ( ) 와 equals ( ) 를 재정의해 동등 객체가 될 조건을 정해야 한다. 때문에 키 타입은 hashCode ( ) 와 equals ( ) 메서드가 재정의되어 있는 String 타입을 주로 사용한다.
Map<K, V> map = new HashMap<K, V>();
HashMap 과 거의 동일하지만 Map 에 추가되는 순서를 유지한다는 점이 다르다.
키 객체를 만드는 법은 HashMap 과 동일하나 HashTable 은 스레드 동기화가 된 상태이므로 복수의 스레드가 동시에 HashTable 에 접근해 객체를 추가하거나 삭제해도 스레드에 안전하다.
키와 값을 String 타입으로 제한한 Map 컬렉션이다.
주로 프로퍼티 파일을 읽어 들일 때 사용한다.
프로퍼티 파일
이란 옵션 정보나 데이터베이스 연결정보 및 다국어 정보를 기록하여 텍스트 파일로 활용한 것이다. 애플리케이션에서 주로 변경이 잦은 문자열을 저장하여 관리하기 때문에 유지보수를 편리하게 만들어준다.
키와 값이 =
기호로 연결되어 있는 텍스트 파일로 ISO 8859-1 문자셋으로 저장되며 한글은 유니코드로 변환되어 저장된다.
TreeMap 은 이진 트리를 기반으로 한 검색 기능을 강화시킨 Map 컬렉션으로 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수로 구성된다. 키와 값이 저장된 Map.Entry
를 저장한다.
오름차순 정렬
TreeSet 의 객체와 TreeMap 의 key 는 저장과 동시에 자동으로 오름차순으로 정렬된다.
정렬을 위해 java.lang.Comparable
을 구현한 객체를 요구한다.
Integer 와 Double 및 String 모두 Comparable 인터페이스를 통해 오름차순이 구현되어 있다.
// StudentService 클래스
public List<Student> sortScore() {
// <?> void java.util.Collections.sort(List<?> list)
// <?> 는 어떤 것이 작성될지 모른다는 의미로 어떤 타입이든 작성 가능
Collections.sort(studentList); // score 기준으로 studentList 오름차순 정렬
Collections.reverse(studentList); // score 기준으로 studentList 내림차순 정렬
return studentList;
}
위 예제는 List 에서 Collections 클래스를 이용한 정렬 방법으로 Collections
는 컬렉션에 도움이 되는 유용한 기능을 모은 클래스이다.
Comparable<T>
인터페이스는 객체의 기본 정렬 기준을 제공하는 인터페이스인데 객체의 정렬 기준 없이 그냥 studentList 를 쓰면 무엇을 기준으로 정렬하라는 것인지 모르기 때문에 자동으로 compareTo 를 호출해서 정렬해주도록 되어있다.
즉 studentList 에 저장된 객체 Student 의 오버라이딩된 compareTo ( ) 메서드를 이용해 정렬이 이루어진다.
// Student 클래스
public class Student implements Comparable<Student> {
public int compareTo(Student other) {
// compareTo() 메서드에서 반환되는 값이
// 0 이하 (음수 또는 0) : 순서 그대로 유지
// 0 초과 (양수) : 리턴값이 양수이면 현재 객체를 오른쪽으로 이동
return this.score - other.score; // [1] 오름차순
// 예) this : 길동 (50점) other : 미영 (40점)
// this.score (50) - other.score (40) = 10 (양수) : 순서 변경
// 예) this : 길동 (40점) other : 미영 (50점)
// this.score (40) - other.score (50) = -10 (음수) : 순서 유지
return other.score - this.score; // [2] 내림차순
// 예) this : 길동 (2) other : 미영 (3)
// other.score (3) - this.score (2) = 1 (양수) : 순서 변경
// 예) this : 길동 (3) other : 미영 (2)
// other.score (2) - this.score (3) = -1 (음수) : 순서 유지
}
}
Student 객체로 이루어진 컬렉션을 정렬하라고 할 때 별도의 다른 기준이 없다면 score 순서로 정렬된다.
내림차순 정렬
내림차순은 따로 구현이 필요하다. TreeSet 과 TreeMap 객체 생성 시 매개변수 생성자를 통해 재정렬이 가능하다.
// TreeSet
TreeSet<E> tSet = new TreeSet(Comparator<? super E> comparator);
// TreeMap
TreeMap<K, V> tMap = new TreeMap(Comparator<? super K> comparator);
또 다른 방법으로는 Integer 와 Double 숫자형과 String 문자열을 제외한 Comparable 을 상속받는 객체인 경우 compareTo ( ) 메서드의 오버라이딩 부분을 내림차순으로 변경하면 된다.