2. Set
2-1. HashSet
HashSet은 Set 인터페이스를 구현한 가장 대표적인 컬렉션이며, Set 인터페이스의 특징대로 HashSet은 중복된 요소를 저장하지 않는다.
그리고 List 인터페이스를 구현한 컬렉션들과 달리, HashSet은 저장순서를 유지하지 않으므로 저장 순서를 유지하고자 한다면 LinkedHashSet을 사용해야 한다.
HashSet이 중복을 막는 법
HashSet는 add메서드를 사용해서 새로운 요소를 추가할 때, 기존의 요소와 동일한 요소인지 판별하기 위해, equals와 hashCode 메서드를 호출한다. 그렇기 때문에, 해당 객체를 set에 넣어서 올바른 결과를 얻기 위해서는 equals와 hashCode 메서드를 목적에 맞게 오버라이딩해야 한다.
public class Main {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new String("abc"));
set.add(new String("abc"));
set.add(new Person2("David", 10));
set.add(new Person2("David", 10));
System.out.println(set);
}
}
class Person2 {
String name;
int age;
Person2(String name, int age) {
this.name = name;
this.age = age;
}
// equals(Object obj) 오버라이딩
public boolean equals(Object obj) {
if (obj instanceof Person2) {
Person2 tmp = (Person2) obj;
System.out.println(tmp.hashCode()+ " " + obj.hashCode());
return name.equals(tmp.name) && age == tmp.age;
}
return false;
}
// hashCode() 오버라이딩
public int hashCode() {
return (name + age).hashCode();
}
public String toString() {
return name + ":" + age;
}
}
2-2. TreeSet
TreeSet은 이진 검색 트리라는 자료구조의 형태로 데이터를 저장하는 컬렉션 클래스이다.
Set 인터페이스로 구현했으므로 중복된 데이터의 저장을 허용하지 않으며, 저장 순서를 유지하지도 않는다.
class TreeNode {
TreeNode left;
Object element;
TreeNode right;
}
이진 트리는 링크드리스트처럼 여러 개의 노드가 서로 연결된 구조로 각 노드에 최대 2개의 노드를 연결할 수 있으며, '루트'라고 불리는 하나의 노드에서부터 시작하여 계속 확장해 나갈 수 있다.
이진 검색 트리는
- 모든 노드는 최대 두 개의 자식노드를 가질 수 있다.
- 왼쪽 자식노드의 값은 부모노드의 값보다 작고 오른쪽 자식노드의 값은 부모노드의 값보다 커야 한다.
- 노드의 추가/삭제에 많은 시간이 소요된다.
- 검색과 정렬에 유리하다.
- 중복된 값은 저장하지 않는다.
3. Map
3-1. HashMap
HashMap은 Map을 구현했으므로 앞에서 살펴본 Map의 특징, 키(key)와 값(value)을 묶어서 하나의 데이터(entry)로 저장한다는 특징을 갖는다.
그리고 해싱을 사용하기 때문에 많은 양의 데이터를 검색하는 데 있어서 뛰어난 성능을 보인다.
- 키(key) : 컬렉션 내의 키(key) 중에서 유일해야 한다.
- 값(value) : 키(key)와 달리 데이터의 중복을 허용한다.
public class HashMapEx1 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("aaaa", "1234"); map.put("asdf", "1111"); map.put("asdf", "1234"); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("id와 pw를 입력해 주세요"); System.out.println("id : "); String id = scanner.nextLine().trim(); System.out.println("pw : "); String pw = scanner.nextLine().trim(); System.out.println(); // 아이디 불일치 if (!map.containsKey(id)) { System.out.println("입력한 id는 존재하지 않습니다. 다시 입력해 주세요."); continue; } else { if (!(map.get(id)).equals(pw)) { System.out.println("비밀번호가 일치하지 않습니다. 다시 입력해주세요."); } else { System.out.println("id와 pw가 일치합니다."); break; } } } } }
3-2. TreeMap
TreeMap은 키와 값의 쌍으로 이루어진 데이터를 이진검색트리의 형태로 저장한다.
HashMap vs. TreeMap
- 검색에 관한 대부분의 경우에서는 HashMap 압승
- 범위 검색이나 정렬이 필요한 경우 TreeMap 사용 권장
3-3. Properties
Properties는 HashMap의 구버전인 HashTable을 상속받아 구현한 것으로, (Object, Object)의 형태인 HashTable에 비해 Properties는 (String, String) 형태라 단순한 컬렉션 클래스이다.
주로 애플리케이션의 환경설정과 관련된 속성을 저장하는 데 사용하며 간단한 입출력이 필요할 때 사용하면 좋다.
컬렉션 클래스 정리 & 요약
컬렉션 | 특 징 |
---|---|
ArrayList | 배열 기반 데이터의 추가 및 삭제에 불리하지만 순차적인 추가 및 삭제는 제일 빠름 임의의 요소에 대한 접근성이 매우 뛰어남 |
LinkedLst | 연결 기반 데이터의 추가와 삭제에 유리함 임의의 요소에 대한 접근성이 좋지 않음 |
HashMap | 배열과 연결이 결합된 형태 추가, 삭제, 검색, 접근성이 모두 뛰어나며 검색에서 최고성능을 보임 |
TreeMap | 연결 기반 정렬과 검색(특히 범위검색)에 적합함. 검색 성능은 HashMap보다 떨어짐 |
Stack | Vector를 상속받아 구현 (LIFO) |
Queue | LinkedList가 Queue 인터페이스를 구현 (FIFO) |
Properties | Hashtable을 상속받아 구현 (String, String) |
HashSet | Set 인터페이스의 구현체이지만, 내부적으로 HashMap을 사용함 |
TreeSet | Set 인터페이스의 구현체이지만, 내부적으로 TreeMap을 사용함 |
LinkedHashMap, LinkedHashSet |
HashMap과 HashSet에 저장순서 유지 기능을 추가하였음 |
+) HashSet, TreeSet은 HashMap, TreeMap을 사용하여 중복을 제거한다.
참고하기 좋은 글 HashMap과 HashSet의 차이
'Book > 자바의 정석' 카테고리의 다른 글
[자바의 정석] Chapter 14. 람다 (0) | 2023.07.14 |
---|---|
[자바의 정석] Chapter 12. 제네릭, 열거형, 어노테이션 (0) | 2023.07.14 |
[자바의 정석] Chapter 11. 컬렉션 프레임워크 - List (0) | 2023.07.14 |
[자바의 정석] Chapter 8. 예외처리 (0) | 2023.07.14 |
[자바의 정석] Chapter 7. 객체지향 프로그래밍 II - 추상메서드, 인터페이스 (0) | 2023.07.14 |