반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- Redis
- Sharding
- 연습문제
- 코딩
- depromeet
- Spring
- exception
- AOP
- pub.dev
- OAuth
- 코드 트리
- kakao
- 디프만
- nGrinder
- 코드트리
- Oidc
- Kotlin
- 자료구조
- 코딩 테스트
- 코딩테스트
- flutter
- dip
- java
- 운영체제
- Scaffold
- C언어
- 부하 테스트
- 디프만16기
- c
- Kafka
Archives
- Today
- Total
Nick Dev
[JAVA] Map, HashMap, TreeMap, Properties 본문
반응형
반응형
Map
Map이란?
- key : value 쌍으로 존재
- 둘 중 하나만 존재할 수 없음
- key는 해당 Map에서 unique해야만 함
- value는 중복되어도 상관X
Map 인터페이스를 구현한 주요 클래스
- HashMap
- 가장 많이 사용
- TreeMap
- LinkedHashMap
- HashTable
- Map과 다름
- HashTable은 JDK 1.0부터 있었던 클래스
- HashMap은 JDK 1.2부터 만들어짐
- 이때 Collection 인터페이스 만들어짐
기능 HashMap HashTable key, value에 null 저장 가능 여부 가능 불가능 Thread-safe Not Safe Safe 데이터 처리 Collection View Enumeration 객체
- 1,2,3 클래스들은 전부 Not Thread-safe임
Map m = Collection.synchronizedMap(new HashMap(…));
- 이렇게 선언해야 여러 thread에서 동시에 접근해도 문제 발생X
Collection View(HashMap)와 Enumeration(HashTable)의 차이
Collection View(HashMap)
keySet()
,values()
,entrySet()
등의 메소드를 통해 Map의 내용을 Collection View 형태로 볼 수 있음keySet()
: Map의 모든 키를Set
객체로 반환values()
: Map의 모든 값을Collection
객체로 반환entrySet()
: Map의 모든 key-value 쌍을Entry
객체의Set
으로 반환
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// Collection View를 사용한 반복
for (Map.**Entry<String, Integer>** entry : map.**entrySet()**) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
Enumeration(HashTable)
keys()
메소드는 Map의 키에 대한Enumeration
을 반환하고,elements()
메소드는 값에 대한Enumeration
을 반환Enumeration
은Iterator
의 구식 버전
keys()
: Map의 모든 키에 대한Enumeration
객체를 반환합니다.elements()
: Map의 모든 값에 대한Enumeration
객체를 반환합니다
import java.util.Hashtable;
import java.util.Enumeration;
public class HashtableExample {
public static void main(String[] args) {
Hashtable<String, Integer> table = new Hashtable<>();
table.put("One", 1);
table.put("Two", 2);
table.put("Three", 3);
// Enumeration을 사용한 키 반복
**Enumeration<String> keys = table.keys();**
while (**keys.hasMoreElements()**) {
String key = keys.**nextElement()**;
System.out.println(key + " = " + table.get(key));
}
}
}
HashMap
HashMap의 상속 관계
java.util.Object
java.util.AbstractMap<K, V>
java.util.HashMap<K, V>
- 대부분의 주요 메서드들은
AbstractMap
클래스가 구현함
특정 클래스를 HashMap의 key로 사용할 때 주의점
- 기본적으로 key는 기본 자료형, 참조 자료형 모두 가능
- 직접 특정 클래스 생성 후, 그 클래스를 key로 사용하면
Object
클래스의hashcode()
,equals()
메소드 잘 구현해야 함 HashMap
에 객체가 들어가면 그 객체의hashcode()
결과 값에 따라 bucket이 만들어짐- 만약 서로 다른 key 저장되었는데,
hashcode()
결과 값이 동일하면 같은 bucket에 여러 개의 값이 들어갈 수 있음(=충돌) get()
호출 시,hashcode()
결과 확인 후, bucket에 여러 개 data 존재할 경우equals()
로 동일한 값을 찾게 된다
- 만약 서로 다른 key 저장되었는데,
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
class Book {
private String title;
private String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(title, book.title) &&
Objects.equals(author, book.author);
}
@Override
public int hashCode() {
return Objects.hash(title, author);
}
}
public class HashMapExample {
public static void main(String[] args) {
Map<Book, Integer> books = new HashMap<>();
Book book1 = new Book("Effective Java", "Joshua Bloch");
Book book2 = new Book("Java Concurrency in Practice", "Brian Goetz");
books.put(book1, 1);
books.put(book2, 2);
// 동일한 속성을 가진 새 객체를 생성
Book book3 = new Book("Effective Java", "Joshua Bloch");
// book3는 book1과 같은 속성을 가지므로, 같은 hashCode를 가질 것이고 equals()에서 true를 반환할 것이다.
System.out.println("Book1's hashcode: " + book1.hashCode());
System.out.println("Book3's hashcode: " + book3.hashCode());
System.out.println("Book1 and Book3 are equal: " + book1.equals(book3));
System.out.println("Number of copies of 'Effective Java': " + books.get(book3));
}
}
Book
클래스는title
과author
필드를 기반으로hashCode()
와equals()
메소드를 재정의- 같은 제목과 저자를 가진
Book
객체들은 동일한 해시코드 →equals()
메소드에서true
를 반환함
- 같은 제목과 저자를 가진
book1
과book3
이 같은 속성book3
을 사용하여book1
을 키로 가지는 값을 성공적으로 검색 가능
- 결론 :
hashcode()
와equals()
구현해라
Map에서 존재하지 않는 key로 get()하면?
- Exception이 아닌
**null**
을 반환해버린다
HashMap은 순서가 중요?!
Set
,Map
자료 구조는 순서가 중요하지 않다
key만 알고 싶어!
**keySet()**
을 통해 해당 hashMap에 어떤 key들이 있는지 알 수 있음- 리턴 타입 :
Set
Set
의 제네릭 타입은 선언한 HashMap의 Key의 제네릭 타입HashMap<**String**, Integer> map = new HashMap<>();
**Set<String>** keySet = map.**keySet()**;
value만 알고 싶어!
**values()**
을 통해 해당 hashMap에 어떤 value들이 있는지 알 수 있음- 리턴 타입 :
Collection
- Collection의 제네릭 타입은 선언한 HashMap의 value의 제네릭 타입
HashMap<String, **Integer**> map = new HashMap<>();
**Collection<Integer>** values = map.**values()**;
Key, Value 세트로 알고 싶어!
**entrySet()**
을 통해 Key와 Value를 세트로 알 수 있다- 리턴 타입 :
Set<Map.Entry<>>
Set
타입으로 리턴,Set
내에는Entry
타입으로 데이터가 저장되어 있음HashMap<String, Integer> map = new HashMap<>();
Set<**Map.Entry<String, Integer>**> entries = new map.entrySet();
containsKey(obj), containsValue(obj)
- 매개 변수로 넘긴 키, 값이 존재하는지 true, false로 알려줌
왜 containsKey()
를 써야될까?
- 해당 key가 존재하는지 확인할 때
get(obj) == null
방식으로도 확인 가능한데 왜containsKey()
를 쓰는게 효과적일까?
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("1", null);
if (hashMap.get("1") == null) {
System.out.println(hashMap.get("1"));
}
- 위의 경우,
1
에 대한 value에 명시적으로null
이 저장되어 있다면**hashMap.get("1") == null
이 구문은true
가 된다** - 우리의 의도는 key가
1
인게 있는지 없는지 여부- 존재하지만 존재하지 않는 것으로 잘못 해석될 수 있음
- 성능 상의 차이는 거의 없음
- 명확한 의도와 정확한 결과를 위해
containsKey()
쓰는게 좋다
TreeMap
TreeMap이란?
- Key를 정렬해서 저장하고, Key목록 가져와서 출력하면 정렬된 순서대로 제공
언제 TreeMap을 쓸까?
- 정렬된 Key 목록을 원할 때
- 매우 많은 데이터일 때는 HashMap보다 느림 / 정렬된 Key 필요 없으면 HashMap이 더 성능 좋음
- 100~1000건 데이터 처리 & 정렬 필요 ⇒ HashMap보다 TreeMap 사용
정렬 순서
- 숫자 > 알파벳 대문자 > 알파벳 소문자 > 한글 순서로 정렬되서 저장
TreeMap은 어떻게 Key를 정렬할까?
- SortedMap 인터페이스를 구현했기 때문에 가능
- SortedMap 인터페이스를 구현한 클래스들은 모두 키가 정렬되어 있어야 함
- red-black Tree 사용해 구현되어 있음
- O(logN)의 시간복잡도
- 성능 좋은편
그 때 그때 정렬해서 쓰면 되지 왜 Key를 정렬한 클래스가 존재하는거야?
- Key가 정렬되어 있다면 맨 앞, 뒤 또는 특정 Key 앞, 뒤에 있는 Key를 알 수 있는 메서드 제공 가능
firstKey()
: 가장 앞에 있는 KeylastKey()
: 가장 뒤에 있는 KeyhigherKey(K key)
: 특정 Key 바로 뒤에 있는 KeylowerKey(K key)
: 특정 Key 바로 앞에 있는 Key~~Map<String, Integer> map = new TreeMap<>(); String firstKey = map.firstKey():~~
- ⚠️ 이 메서드들 쓰려면
Map
인터페이스로 UpCasting하면 안된다 ⚠️ - TreeMap*<String, Integer> treeMap = new TreeMap<>();
String firstKey = map.firstKey():
Properties 클래스
특징
HashTable
을 extends 했기에Map
인터페이스에서 제공하는 모든 메서드 사용 가능- 자바에서 시스템 속성 알려주는 클래스
Properties prop = System.getProperties();
System
클래스에static
메서드인getProperties()
호출하면Properties
객체 리턴
굳이 Properties
클래스 사용하는 이유는?!
Properties
에서 추가로 제공하는 메서드들 때문에- 파일에서 읽어오고, 파일에 저장하고, 저장할 때 주석도 같이 넣어주는 메서드들 때문에
load()
,store()
,storeToXML()
…
Java의 자료 구조 정리
Collection
List
: 배열처럼 목록 처리ArrayList
LinkedList
Set
: 중복 X, 순서 XHashSet
LinkedHashSet
TreeSet
Queue
: 들어온 순서대로 처리(FIFO)LinkedList
PriorityQueue
Map
: Key-Value 형식으로 저장HashMap
: 가장 많이 씀LinkedHashMap
TreeMap
- 메서드
ketSet()
으로Set
타입의 key목록 리턴valuse()
로Collection
타입의 valuse 목록 리턴for loop
ORIterator
로 데이터 처리
직접해 봅시다
package second_chapter06_map;
import java.util.Hashtable;
import java.util.Random;
import java.util.Set;
public class RandomNumberStatistics {
public static void main(String[] args) {
RandomNumberStatistics sample = new RandomNumberStatistics();
sample.getRandomNumberStatistics();
}
private final int DATA_BOUNDARY = 50;
Hashtable<Integer, Integer> hashtable = new Hashtable<>();
public void getRandomNumberStatistics() {
for (int i = 0; i < 5000; i++) {
Random random = new Random();
putCurrentNumber(random.nextInt(1, DATA_BOUNDARY+1));
}
printStatistics();
}
public void putCurrentNumber(int tempNumber) {
if (hashtable.containsKey(tempNumber)) {
hashtable.put(tempNumber, hashtable.get(tempNumber)+1);
}
else {
hashtable.put(tempNumber, 1);
}
}
public void printStatistics() {
Set<Integer> keySet = hashtable.keySet();
for (int key:keySet) {
System.out.print(key + "=" + hashtable.get(key) + "\t");
// key가 1로 끝날 때마다 줄바꿈 넣자 -> 그래야 한 줄에 10개씩 이쁘게 출력
if (key%10-1==0) System.out.println();
}
}
}
정리해 봅시다
1. Map 형태의 자료 구조는 무엇과 무엇으로 구성되어 있나요
Key와 Value로 구성
2. Map에서 데이터를 저장하는 메서드
put()
3. Map에서 특정 키에 할당된 값을 가져오는 메서드
get()
4. Map에서 특정 키와 관련된 키와 데이터를 지우는 메서드
remove()
5. Map에서 키의 목록을 가져오는 메서드
keySet()
6. Map에 저장되어 있는 데이터의 크기를 가져오는 메서드
size()
7. HashMap과 HashTable 중에서 키나 값에 null을 저장할 수 있는 것은?
HashMap
8. HashMap과 HashTable 중 여러 쓰레드에서 동시 접근해도 문제 없는 것은?
HashTable
9. HashMap에서 특정 키가 존재하는지 확인하는 메서드
containsKey()
10. 키가 저장되면서 정렬되는 Map은?
TreeMap
11. Properties 클래스는 어떤 클래스를 확장한 것인가?
HashTable
12. Properties 클래스의 객체에 있는 데이터를 파일로 저장할 때에는 어떤 메서드들을 사용하면 되나요?
store()
,storeToXML()
메서드 사용
반응형
'Java' 카테고리의 다른 글
[JAVA] try-with-resources 써야 돼? (0) | 2024.12.11 |
---|---|
[JAVA] Exception과 Error, Checked와 Unchecked (0) | 2024.12.11 |
[JAVA] Heap 구조, GC 동작 방식 그리고 GC 알고리즘 5가지 (1) | 2024.12.11 |
[JAVA] JVM의 Runtime Data Area (0) | 2024.12.11 |
[JAVA] Thread 생성과 핵심 메서드 (0) | 2024.12.11 |