HashMap
TreeMap
LinkedHashMap
HashTable
기능 | HashMap | HashTable |
---|---|---|
key, value에 null 저장 가능 여부 | 가능 | 불가능 |
Thread-safe | Not Safe | Safe |
데이터 처리 | Collection View | Enumeration 객체 |
Map m = Collection.synchronizedMap(new 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());
}
}
}
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));
}
}
}
java.util.Object
java.util.AbstractMap<K, V>
java.util.HashMap<K, V>
AbstractMap
클래스가 구현함Object
클래스의 hashcode()
, equals()
메소드 잘 구현해야 함HashMap
에 객체가 들어가면 그 객체의 hashcode()
결과 값에 따라 bucket이 만들어짐hashcode()
결과 값이 동일하면 같은 bucket에 여러 개의 값이 들어갈 수 있음(=충돌)get()
호출 시, hashcode()
결과 확인 후, bucket에 여러 개 data 존재할 경우 equals()
로 동일한 값을 찾게 된다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()
구현해라**null**
을 반환해버린다Set
, Map
자료 구조는 순서가 중요하지 않다**keySet()**
을 통해 해당 hashMap에 어떤 key들이 있는지 알 수 있음Set
Set
의 제네릭 타입은 선언한 HashMap의 Key의 제네릭 타입HashMap<**String**, Integer> map = new HashMap<>();
**Set<String>** keySet = map.**keySet()**;
**values()**
을 통해 해당 hashMap에 어떤 value들이 있는지 알 수 있음Collection
HashMap<String, **Integer**> map = new HashMap<>();
**Collection<Integer>** values = map.**values()**;
**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)
containsKey()
를 써야될까?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
가 된다**1
인게 있는지 없는지 여부containsKey()
쓰는게 좋다firstKey()
: 가장 앞에 있는 Key
lastKey()
: 가장 뒤에 있는 Key
higherKey(K key)
: 특정 Key 바로 뒤에 있는 Key
lowerKey(K key)
: 특정 Key 바로 앞에 있는 Key
⚠️ 이 메서드들 쓰려면 Map
인터페이스로 UpCasting하면 안된다 ⚠️
~~Map<String, Integer> map = new TreeMap<>();
String firstKey = map.firstKey():~~
**TreeMap**<String, Integer> treeMap = new TreeMap<>();
String firstKey = map.firstKey():
HashTable
을 extends 했기에 Map
인터페이스에서 제공하는 모든 메서드 사용 가능Properties prop = System.getProperties();
System
클래스에 static
메서드인 getProperties()
호출하면 Properties
객체 리턴Properties
클래스 사용하는 이유는?!Properties
에서 추가로 제공하는 메서드들 때문에load()
, store()
, storeToXML()
…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
OR Iterator
로 데이터 처리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();
}
}
}
Key와 Value로 구성
put()
get()
remove()
keySet()
size()
HashMap
HashTable
containsKey()
TreeMap
HashTable
store()
, storeToXML()
메서드 사용