jdk 7 에서 HashMap 의 지식 포인트 요약
기본 초기 용량 은 2 의 n 제곱 이 어야 합 니 다.
static final int DEFAULT_INITIAL_CAPACITY = 16;
최대 용량 은 구조 방법 을 통 해 들 어 오 는 용량 이 그것 보다 더 클 때 이 최대 용량 으로 2 의 n 제곱 이 어야 한다.
static final int MAXIMUM_CAPACITY = 1 << 30;
기본 부하 인자
static final float DEFAULT_LOAD_FACTOR = 0.75f;
키 쌍 을 저장 하 는 데 사용 합 니 다.키 쌍 은 모두 Entry 에 저 장 된 것 을 볼 수 있 습 니 다.
transient Entry<K,V>[] table;
//capacity * load factor,
int threshold;
HashMap 의 요 소 는 table 이라는 Entry 배열 로 저 장 됩 니 다.기본 크기 는 16 입 니 다.capacity:배열 의 용량
기억 구조
Entry 는 key 와 value 뿐만 아니 라 다음 next 를 가리 킬 수 있 는 링크 구조 입 니 다.
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
...
put 방법
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
우선 hash 방법 을 통 해 hashcode 를 처리 합 니 다:
final int hash(Object k) {
int h = 0;
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
key 의 hashcode 값 에서 만 처 리 된 것 을 볼 수 있 습 니 다.hash 를 통 해 계 산 된 값 은 index For 방법 으로 있 을 table 아래 표 시 를 찾 을 수 있 습 니 다.
static int indexFor(int h, int length) {
return h & (length-1);
}
이 방법 은 사실 대 4 567914 에 해당 한다.삽입 할 key 가 null 일 때 putForNullKey 방법 으로 처리 합 니 다.
private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(0, null, value, 0);
return null;
}
puutForNullKey 방법 은table.length
이 위치 에서 만 옮 겨 다 닙 니 다.key 는 null 이 고 table 의 첫 번 째 위치 에 만 놓 여 있 기 때문에 아래 는 0 으로 표시 되 어 있 습 니 다.옮 겨 다 니 면서 key 가 null 인 것 을 발견 하면 새 value 를 바 꾸 고 오래된 value 로 돌아 가 끝 납 니 다.만약 key 가 null 이 아니라면,addEntry 방법 으로 Entry 를 추가 합 니 다.
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
jdk 7 에서 resize 의 조건 이 바 뀌 었 음 을 볼 수 있 습 니 다.4.567914.그리고 table 에 있 는 홈 에 Entry 가 있 을 때 만 resize 가 발생 합 니 다.즉,4.567914.하지만 홈 마다 적어도 하나의 Entry 가 있 을 때 까지 기 다 려 야 확대 할 수 있다.그리고 사이즈 조절 할 때마다 용량 이 배로 늘 어 납 니 다.
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
마지막 으로 createEntry 를 보 세 요.이 통 의 첫 번 째 Entry 를 저장 하고 새로운 Entry 를 만들어 첫 번 째 위치 에 두 고 원래 의 Entry 를 뒤에 연결 합 니 다.여기 서 사용 하 는 것 은 머리 삽입 법 으로 요 소 를 삽입 하 는 것 이다.get 방법
사실 get 방법 과 put 방법 은 똑같다.
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
key 가 null 일 때,가 져 가세 요table[0]
가 져 가세 요:
private V getForNullKey() {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null)
return e.value;
}
return null;
}
그렇지 않 으 면 getEntry 방법 을 호출 합 니 다:
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
이 방법 도 key 의 hashcode 를 통 해 아래 표 시 를 계산 하고 이 아래 표 시 된 Entry 체인 을 옮 겨 다 니 며 key 의 메모리 주소 가 같 거나 equals 가 같 으 면 찾 았 음 을 설명 합 니 다.hash 의 원칙
A.등 멱 성.Hash 값 을 가 져 오 는 작업 을 몇 번 을 수행 하 든 대상 이 변 하지 않 는 다 면 Hash 값 은 고정 되 어 있 습 니 다.처음 가 져 오 는 것 이 N 번 가 져 오 는 것 과 다르다 면 사용 하기 가 매우 번거롭다.
B.대등 성.두 대상 equal 방법 이 true 로 되 돌아 오 면 hash 값 도 같 아야 합 니 다.예 를 들 어 obba 를 key 로 HashMap 에 저장 한 다음 new 는 obdb 를 만 들 었 습 니 다.당신 이 보기에 obj B 와 obj A 는 하나의 물건(그들 equal 때 문)이지 만,obj B 를 사용 하여 hashMap 에서 물건 을 꺼 낼 수 없습니다.
C.서로 이성.두 대상 equal 방법 이 false 로 되 돌아 가면 hash 값 이 같 을 수 있 지만 다른 것 이 좋 습 니 다.이것 은 필요 한 것 이 아니 라 이렇게 하면 hash 류 작업 의 성능(충돌 확률 이 낮 음)을 향상 시 킬 수 있 습 니 다.
hash 충돌 해결 방법:
개방 주소 법
체인 주소 법
hashmap 는 체인 주소 법 을 사용 합 니 다.이런 방법 은 퇴적 현상 이 없 지만 next 지침 은 추가 공간 을 차지 합 니 다.
jdk 8 의 HashMap 과 구별
jdk 8 에 서 는
size>=threshold
hash 값 을 계산 한 다음 에 이 hash 값 을 통 해 이 key 를 찾 습 니 다.그러나 충돌 이 발생 할 때 링크 와 빨 간 검 은 나무 두 가지 방법 으로 처리 합 니 다.노드 개수 가 적 을 때 링크(Node 로 저장)를 사용 하고 개수 가 많 을 때 빨 간 검 은 나무(TreeNode 로 저장)를 사용 하 며 노드 도 Entry 라 고 부 르 지 않 습 니 다.노드 와 트 리 노드 로 나 뉘 었 다.최 악의 경우 링크 가 찾 는 시간 복잡 도 는 O(n)이 고 빨 간 검 은 나 무 는 O(logn)이 므 로 HashMap 의 효율 을 높 일 수 있다.jdk 8 의 HashMap 에서 변 수 를 정의 합 니 다 TREEIFYTHRESHOLD,노드 개수 로>=TREEIFYTHRESHOLD-1 시,HashMap 은 붉 은 검 은 나무 로 저 장 됩 니 다.총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
2022년 3월 21일 TIL1. JVM & JDK JVM JRE 자바 실행 환경의 약자로 자바 프로그램을 실행하기 위한 도구들이 들어있으며 JVM이 이 안에 포함된다 JDK JRE + 개발툴 javac는 컴파일 명령어 HelloWorld.cl...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.