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
- 재택치료
- 지독한 컨셉충
- 확진
- CRUDS
- FLUTTER
- 수제비 2022
- 교수님 과제 이제 그만..
- pem키 분실
- 다음에 또 만나자
- 스프링 MVC
- 레이튼 교수와 이상한 마을
- 대외활동
- 정보처리기사 2022
- N-Queen
- 아싸의 생일
- 뽀모도로 타이머
- 얘들아 잘 지내니
- 수제비2022 정리
- AWS
- 개강해짐
- 플러터
- 자가격리
- 교육봉사
- 다행이야...ㅎ
- 생일축하해 나 자신
- 대학생
- 정보처리기사2022
- 모바일 청첩장
- 다들 안잊어서
- 2022 정보처리기사
Archives
- Today
- Total
Rei’s Tech diary
Map - LinkedHashMap 이론과 구현 본문
📌 LinkedHashMap<K, V>
- HashMap<K, V>와 동일한 기능 수행
- 입력 순서와 출력순서가 같다.
📌 Map<K, V> 컬렉션의 주요 메서드
Map<K, V>의 구현 클래스는 아래의 모든 메서드를 포함한다.
구분 | 리턴타입 | 메서드 이름 | 기능 |
데이터 추가 |
V | put(K key, V value) | 입력 매개변수(키,값)을 Map객체에 추가 |
void | putAll(Map<? extends K, ? extends V> m) | 입력매개변수의 Map객체를 통제로 추가 | |
데이터 변경 |
V | replace(K key, V value) | Key 값에 해당하는 값을 value로 변경 (old값 리턴) (단, 해당 key가 없으면 null 리턴) |
boolean | replace(K key, V oldValue, V newValue) | (key, oldValue)의 쌍을 가지는 엔트리에서 값을 newValue로 변경 (단, 해당 엔트리가 없으면 false를 리턴) |
|
데이터 정보추출 |
V | get(Object key) | 매개변수의 key값에 해당하는 valuye 값을 리턴 |
boolean | containsKey(Object key) | 매개변수의 key값이 포함되어 있는지 여부 | |
boolean | containsValue(Object value) | 매개변수의 value 값이 포함되어 있는지 여부 | |
Set<K> | keySet() | Map 데이터들 중 key들만 뽑아서 Set객체로 리턴 | |
Set<Entry<K,V>> | entrySet() | Map의 각 Entry들을 Set 객체로 담아 리턴 | |
int | size() | Map에 포함된 데이터(Entry) 개수 | |
데이터 삭제 |
V | remove(Object key) | 입력 매개변수의 Key를 갖는 엔트리 삭제 (단, 해당 key가 없으면 아무런 동작을 안함) |
boolean | remove(Object key, Object value) | 입력 배개변수의 (key, value)를 갖는 엔트리 삭제 (단, 해당 엔트리가 없으면 아무런 동작 안함) |
|
void | clear() | Map 객체내의 모든 데이터 삭제 |
예시코드)
public class LinkedHashMapMethod {
public static void main(String[] args) {
Map<Integer, String> lhMap1 = new LinkedHashMap<>();
//#1. put (K key, V value)
lhMap1.put(1, "나다라");
lhMap1.put(2, "가나다");
lhMap1.put(3, "다라마");
System.out.println(lhMap1.toString()); //{1=나다라, 2=가나다, 3=다라마}
//#2. putAll(다른객체)
Map<Integer, String> lhMap2 = new LinkedHashMap<>();
lhMap2.putAll(lhMap1);
System.out.println(lhMap2.toString()); //{1=나다라, 2=가나다, 3=다라마}
//#3. replace(K key, V value)
lhMap2.replace(1, "가가가");
lhMap2.replace(4, "라라라"); //동작안함
System.out.println(lhMap2.toString()); //{1=가가가, 2=가나다, 3=다라마}
//#4. replace(K key, V oldValue, V new Value)
lhMap2.replace(1, "가가가", "나나나");
lhMap2.replace(2, "다다다", "라라라"); //동작안함
System.out.println(lhMap2); //{1=나나나, 2=가나다, 3=다라마}
//#5. v get(Object key)
System.out.println(lhMap2.get(1)); //나나나
System.out.println(lhMap2.get(2)); //가나다
System.out.println(lhMap2.get(3)); //다라마
//#6. containsKey(Object key)
System.out.println(lhMap2.containsKey(1)); //true
System.out.println(lhMap2.containsKey(5)); //false
//#7. containsValue(Object value)
System.out.println(lhMap2.containsValue("나나나")); //true
System.out.println(lhMap2.containsValue("다다다")); //false
//#8. Set<K> keySet()
Set<Integer> keySet = lhMap2.keySet();
System.out.println(keySet.toString()); //[1, 2, 3]
//#9. Set<Map.Entry<K,V>> entrySet()
Set<Map.Entry<Integer, String>> entrySet = lhMap2.entrySet();
System.out.println(entrySet.toString()); //[1=나나나, 2=가나다, 3=다라마]
//#10. size()
System.out.println(lhMap2.size()); //3
//#11. remove(Object key)
lhMap2.remove(1);
lhMap2.remove(4); //동작안함
System.out.println(lhMap2.toString()); //{2=가나다, 3=다라마}
//#12. remove(Object key, Object value)
lhMap2.remove(2, "가나다");
lhMap2.remove(3, "다다다"); //동작안함
System.out.println(lhMap2.toString()); //{3=다라마}
//#13. clear()
lhMap2.clear();
System.out.println(lhMap2.toString());//{}
}
}
💡 LinkedHashMap 구현
import java.util.HashMap;
public class MyLinkedHashMap<K, V>{
private static class Entry<K, V>{
K key;
V value;
Entry<K, V> prev;
Entry<K, V> next;
Entry(K key, V value){
this.key = key;
this.value = value;
}
}
private final HashMap<K, Entry<K, V>> map;
private Entry<K, V> head;
private Entry<K, V> tail;
private int size;
public MyLinkedHashMap(){
this.map = new HashMap<>();
this.size = 0;
}
public void put(K key, V value){
if(map.containsKey(key)){
Entry<K, V> entry = map.get(key);
entry.value = value;
moveToTail(entry);
}else{
Entry<K, V> entry = new Entry<>(key, value);
addToTail(entry);
map.put(key, entry);
size++;
}
}
public V get(K key){
if(!map.containsKey(key)){
return null;
}
Entry<K, V> entry = map.get(key);
return entry.value;
}
public void remove(K key){
if(!map.containsKey(key)){
return;
}
Entry<K, V> entry = map.get(key);
removeNode(entry);
map.remove(key);
size--;
}
public int size(){
return size;
}
private void removeNode(Entry<K, V> entry){
if(entry.prev != null){
entry.prev.next = entry.next;
}else{
head = entry.next;
}
if(entry.next != null){
entry.next.prev = entry.prev;
}else{
tail = entry.prev;
}
}
private void addToTail(Entry<K, V> entry){
if(tail == null){
head = tail = entry;
} else {
tail.next = entry;
entry.prev = tail;
tail = entry;
}
}
private void moveToTail(Entry<K, V> entry){
removeNode(entry);
addToTail(entry);
}
public void print(){
Entry<K, V> current = head;
while(current != null){
System.out.print(current.key + "=" + current.value + " ");
current = current.next;
}
System.out.println();
}
}
필드, 메서드, 생성자, 내부 클래스
- Entry 클래스: 개별 항목을 저장하며 이전/다음 노드를 가리키는 구조
private static class Entry<K, V> {
K key; // 항목의 키
V value; // 항목의 값
Entry<K, V> prev; // 이전 항목에 대한 참조
Entry<K, V> next; // 다음 항목에 대한 참조
// Entry 생성자: 키와 값을 초기화
Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
private final HashMap<K, Entry<K, V>> map; // 항목을 빠르게 조회하기 위한 HashMap
private Entry<K, V> head; // 연결 리스트의 첫 번째 항목
private Entry<K, V> tail; // 연결 리스트의 마지막 항목
private int size; // 항목의 총 개수
public MyLinkedHashMap() {
this.map = new HashMap<>();
this.size = 0;
}
key - value 쌍 저장 (put)
public void put(K key, V value) {
if (map.containsKey(key)) {
// 키가 이미 존재하면 값을 업데이트하고 리스트 위치 갱신
Entry<K, V> entry = map.get(key);
entry.value = value; // 값 업데이트
moveToTail(entry); // 최신 항목으로 이동
} else {
// 키가 없으면 새로운 항목 추가
Entry<K, V> entry = new Entry<>(key, value);
addToTail(entry); // 리스트 끝에 추가
map.put(key, entry); // HashMap에 저장
size++; // 항목 개수 증가
}
}
// removeNode 메서드: 리스트에서 특정 노드 제거
private void removeNode(Entry<K, V> entry) {
if (entry.prev != null) {
entry.prev.next = entry.next; // 이전 노드의 next를 현재 노드의 next로 설정
} else {
head = entry.next; // 첫 번째 노드 제거 시 head 업데이트
}
if (entry.next != null) {
entry.next.prev = entry.prev; // 다음 노드의 prev를 현재 노드의 prev로 설정
} else {
tail = entry.prev; // 마지막 노드 제거 시 tail 업데이트
}
}
// addToTail 메서드: 새로운 노드를 리스트의 끝에 추가
private void addToTail(Entry<K, V> entry) {
if (tail == null) {
// 리스트가 비어있으면 head와 tail 모두 설정
head = tail = entry;
} else {
// 기존 tail 뒤에 새로운 항목 추가
tail.next = entry;
entry.prev = tail;
tail = entry; // tail 업데이트
}
}
// moveToTail 메서드: 특정 노드를 리스트의 끝으로 이동
private void moveToTail(Entry<K, V> entry) {
removeNode(entry); // 기존 위치에서 제거
addToTail(entry); // 리스트 끝에 다시 추가
}
키에 해당하는 값 반환 (get)
public V get(K key) {
if (!map.containsKey(key)) {
return null; // 키가 없으면 null 반환
}
Entry<K, V> entry = map.get(key); // HashMap에서 항목 가져오기
return entry.value; // 값 반환
}
특정 키를 가진 요소 제거 (remove)
public void remove(K key) {
if (!map.containsKey(key)) {
return; // 키가 없으면 아무 작업도 하지 않음
}
Entry<K, V> entry = map.get(key); // HashMap에서 항목 가져오기
removeNode(entry); // 리스트에서 항목 제거
map.remove(key); // HashMap에서 항목 제거
size--; // 항목 개수 감소
}
요소 갯수 반환 size
public int size() {
return size;
}
입력 순서대로 출력
public void print() {
Entry<K, V> current = head; // 리스트의 첫 번째 항목부터 시작
while (current != null) {
System.out.print(current.key + "=" + current.value + " "); // 키=값 출력
current = current.next; // 다음 항목으로 이동
}
System.out.println(); // 줄바꿈
}
'프로그래밍 > Data Structure' 카테고리의 다른 글
Stack 이론과 구현 (0) | 2025.01.02 |
---|---|
Map - TreeMap 이론과 구현 (0) | 2025.01.02 |
Map - HashTable 이론과 구현 (2) | 2025.01.01 |
Map - HashMap 이론과 구현 (2) | 2024.12.30 |
Set - TreeSet 이론과 구현 (0) | 2024.12.28 |