Java에서 HashMap과 HashTable의 차이점은 무엇입니까? HashMap과 HashTable의 간단한 비교
이 기사에서 제공하는 내용은 Java에서 HashMap과 HashTable의 차이점이 무엇입니까? HashMap과 HashTable의 간단한 비교입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
1 먼저 상속 구조를 살펴보겠습니다.
HashMap
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
Hashtable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
1. , 이름 전달 HashMap은 카멜 케이스 명명 규칙을 따르지만 Hashtable은 카멜 케이스 명명 규칙을 따르지 않는다는 것을 알 수 있습니다. 상속 구조를 통해 HashMap은 AbstractMap
2. jdk1.8에서 HashMap의 체인에 저장된 노드의 개수가 8보다 크거나 같을 때 클래스의 속성을 통해 알 수 있습니다. 연결된 목록 배열이 64보다 크면 레드-블랙 트리로 변환되고 Hashtable은 레드-블랙 트리로 변환되지 않습니다.
3. Hashtable의 put() 및 HashMap의 put()
Hashtable의 put 작업:
public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }
Hashtable의 메서드에 동기화 키워드가 추가되었습니다. 그것은 동기화된 방법입니다.
if (value == null) throw new NullPointerException();}을 통해 value의 값이 비어 있는 것을 허용하지 않으며, 키가 null인 경우 key를 호출하는 것을 볼 수 있습니다. hashCode(); 널 포인터 예외가 발생하므로 Hashtable에 저장된 항목의 키와 값은 비어 있을 수 없습니다. 또한 Hashtable은 % 연산을 통해 연결된 목록의 첨자를 얻습니다.
아래 HashMap을 보세요
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
HashMap의 키가 null을 가질 수 있음을 알 수 있습니다. 키가 null이면 해당 해시 값은 0이고 HashMap은 연결된 목록 배열. 대상 방법은 Hashtable과 다릅니다. HashMap의 배열 목록 길이는 2의 n제곱이므로 (n-1)&해시를 사용하여 계산합니다.
Summary: HashMap의 키는 하나의 null을 가질 수 있고, 값은 여러 개의 null을 가질 수 있으며, Hashtable의 키와 값은 비워둘 수 없습니다. 체인 위치를 지정하는 방법이 다릅니다. HashMap은 & 연산을 통해 첨자를 얻는 반면, Hashtable은 %를 통해 첨자를 얻으며 & 연산이 더 빠릅니다.
4. HashMap과 Hashtable은 확장 방법이 다릅니다.
Hashtable 확장:
@SuppressWarnings("unchecked") protected void rehash() { int oldCapacity = table.length; Entry<?,?>[] oldMap = table; // overflow-conscious code int newCapacity = (oldCapacity << 1) + 1; //MAX_ARRAY_SIZE = int的最大值-8 if (newCapacity - MAX_ARRAY_SIZE > 0) { if (oldCapacity == MAX_ARRAY_SIZE) // Keep running with MAX_ARRAY_SIZE buckets return; newCapacity = MAX_ARRAY_SIZE; } Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; modCount++; threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1); table = newMap; //从链表数组尾到头遍历 for (int i = oldCapacity ; i-- > 0 ;) { for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) { Entry<K,V> e = old; old = old.next; //从新定位链位置 int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = (Entry<K,V>)newMap[index]; newMap[index] = e; } } }
소스 코드를 통해 Hashtable 연결 목록 배열의 최대 길이가 int 유형 -8의 최대값임을 확인했습니다. Hashtable의 길이는 원래 2배의 1로 변경되며 연결된 목록은 확장 후 위치를 변경해야 합니다. 게다가 확장 후에는 배열 연결 리스트의 순서가 원래 순서의 역순이 됩니다.
HashMap 확장:
final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; //如果远链表数组长度大于零 if (oldCap > 0) { //如果原长度大于或等于MAXIMUM_CAPACITY(2^30),则将threshold(闸值)设为Integer.MAX_VALUE大约为MAXIMUM_CAPACITY(2^30)的二倍 if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } //让新的容量变为旧的二倍 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) //新的闸值也变为原来的二倍 newThr = oldThr << 1; // double threshold } //老的链表数组长度小于等于0,老的闸值大于零,这种情况是初始化时传入一个map导致的构造器为public HashMap(Map<? extends K, ? extends V> m) else if (oldThr > 0) // initial capacity was placed in threshold //让新的容量等于旧的闸值 newCap = oldThr; //下面的else是默认的构造器,即public HashMap() else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } //新的闸值为零时(也就是(newCap = oldCap << 1) >= MAXIMUM_CAPACITY的情况),这时需要赋予newThr正确的值。 if (newThr == 0) { float ft = (float)newCap * loadFactor; //闸值=链表数组长度*加载因子。 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; //扩容,如果原来的链表数组中有数据,就复杂到table中 @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; if (oldTab != null) { //遍历老的链表数组 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; //当oldTab[j]这条链不为空时 if ((e = oldTab[j]) != null) { oldTab[j] = null; //如果这条链只有首节点有数据,把它添加进新链表数组中 if (e.next == null) //因为数组的容量时2的n次方,所以使用hash&(newCap-1)来计算出在那条链中。 newTab[e.hash & (newCap - 1)] = e; //如果老的链在红黑树中,使用split()方法来复制 else if (e instanceof TreeNode) ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); //当前链中不只只有一个链表头数据时,遍历链表来复制 else { // preserve order //数据的复制有两种情况,第一种是原位置不变,第二种是位置改变 loHead代表和原链相同位置的链,hiHead代表是原链加上原容量的链,因为扩容后长度为原长度的二倍,一个链中的节点要不在原位置的链中,要么在原位置加原容量的链中 Node<K,V> loHead = null, loTail = null; Node<K,V> hiHead = null, hiTail = null; Node<K,V> next; do { next = e.next; //通过e.hash和oldCap进行&运算来得出位置是否需要改变。 比如原数组容量为16(10000)和hash值进行&运算,如果高位1未参加运算,则为0即位置不变,如果高位参加了运算值不等于0,需要改变位置。 //loHead和hiHead分别代表原位置的链和新位置的链 if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); if (loTail != null) { loTail.next = null; //原位置为j newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; //新位置为j+oldCap newTab[j + oldCap] = hiHead; } } } } } return newTab; }
HashMap의 확장 용량이 두 배로 늘어난 것을 볼 수 있으며, 확장된 위치는 다음 중 하나이므로 연결 리스트의 위치를 변경할 필요가 없습니다. 원래 위치는 원래 위치 + 원래 용량 중 하나입니다. 이는 해시와 연결된 목록 배열의 길이를 AND하여 결정할 수 있습니다. 배열 길이의 상위 비트가 계산에 참여하는 경우 해당 위치에 있게 됩니다. 원래 위치 + 원래 용량. 배열 길이의 상위 비트가 계산에 포함되지 않으면 원래 위치에 있게 됩니다. 또한 HashMap이 확장된 후에도 연결 목록 데이터의 순서는 변경되지 않습니다.
5. HashMap과 Hashtable의 초기 용량은 다릅니다.
Hashtable의 초기 용량은 11이고, HashMap의 초기 용량은 16입니다.
위 내용은 Java에서 HashMap과 HashTable의 차이점은 무엇입니까? HashMap과 HashTable의 간단한 비교의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











해시맵의 확장 메커니즘은 용량을 다시 계산하고 원래 배열을 새 배열로 교체하는 것입니다. 원본 배열의 모든 데이터를 다시 계산하여 새 배열을 삽입한 후 새 배열을 가리키며, 용량 확장 전 배열이 최대값에 도달한 경우 직접 임계값을 최대 정수로 설정하고 반환합니다.

HashMap 클래스의 put() 메소드를 사용하여 HashMap에 키-값 쌍을 삽입하는 방법 HashMap은 Java 컬렉션 프레임워크에서 매우 중요한 클래스입니다. 실제 개발에서는 HashMap 클래스의 put() 메서드를 사용하여 쉽게 구현할 수 있는 키-값 쌍을 HashMap에 삽입해야 하는 경우가 많습니다. HashMap의 put() 메소드의 서명은 다음과 같습니다: Vput(Kkey,Vvalue)

javaHashMap에 중복된 Key 값 삽입 HashMap에 중복된 값을 삽입하려면 먼저 HashMap에 요소가 어떻게 저장되어 있는지 파악해야 합니다. Put 메소드 Map에 저장된 각 요소는 키-값 쌍이며 모두 Put 메소드를 통해 추가되며 동일한 키는 Map에서 하나의 연관된 값만 갖습니다. Put 메소드는 Map에서 다음과 같이 정의됩니다. Vput(Kkey,Vvalue); put() 메소드 구현: 먼저 hash(key)는 키의 hashcode()를 가져오고, hashmap은 얻은 해시코드를 기반으로 삽입할 위치가 있는 체인을 찾습니다.

Java 문서 해석: HashMap 클래스의 containKey() 메소드 사용법에 대한 자세한 설명이 필요합니다. 소개: HashMap은 Java에서 일반적으로 사용되는 데이터 구조입니다. ContainsKey() 메서드는 HashMap에 지정된 키가 포함되어 있는지 확인하는 데 사용됩니다. 이 문서에서는 HashMap 클래스의 containKey() 메서드를 사용하는 방법을 자세히 설명하고 구체적인 코드 예제를 제공합니다. 1. 계속

1. Map은 기본적으로 HashMap을 사용할 수 있는데, HashMap에 문제가 있다고 설명합니다. 즉, HashMap을 반복하는 순서가 HashMap이 배치된 순서와 다르거나 순서가 맞지 않는다는 것입니다. HashMap의 이러한 단점은 종종 문제를 야기합니다. 일부 시나리오에서는 LinkedHashMap인 정렬된 맵을 기대하기 때문입니다. 2. 차이점 인스턴스 publicstaticvoidmain(String[]args){Mapmap=newLinkedHashMap();map.put("apple","Apple");map.put("

Java는 HashMap 클래스의 putAll() 함수를 사용하여 Map을 다른 Map에 추가합니다. Map은 Java에서 일반적으로 사용되는 데이터 구조이며 키-값 쌍의 컬렉션을 나타내는 데 사용됩니다. Java의 컬렉션 프레임워크에서 HashMap은 일반적으로 사용되는 구현 클래스입니다. 이는 데이터 병합 및 복사를 용이하게 하기 위해 하나의 맵을 다른 맵에 추가하는 데 사용되는 putAll() 함수를 제공합니다. 이 기사에서는 putAll() 함수를 사용하는 방법을 소개하고 해당 코드 예제를 제공합니다. 첫 번째,

JavaMap은 Java 표준 라이브러리에서 일반적으로 사용되는 데이터 구조로, 키-값 쌍의 형태로 데이터를 저장합니다. Map의 성능은 애플리케이션의 실행 효율성에 매우 중요합니다. Map의 성능이 좋지 않으면 애플리케이션이 느리게 실행되거나 충돌할 수도 있습니다. 1. 적절한 맵 구현 선택 Java는 HashMap, TreeMap 및 LinkedHashMap을 포함한 다양한 맵 구현을 제공합니다. 각 맵 구현에는 고유한 장점과 단점이 있습니다. 맵 구현을 선택할 때는 애플리케이션의 특정 요구 사항에 따라 적절한 구현을 선택해야 합니다. HashMap: HashMap은 가장 일반적으로 사용되는 맵 구현입니다. 해시 테이블을 사용하여 데이터를 저장하고 삽입, 삭제 및 검색 속도가 더 빠릅니다.

1. 싱글턴 패턴이란 무엇인가요? 싱글톤 패턴은 객체의 특정 인스턴스를 생성하는 데 사용되는 객체 생성 패턴으로, 시스템에서 클래스의 인스턴스가 하나만 생성되도록 할 수 있습니다. Java로 구현된 싱글톤은 가상 머신의 범위 내에 있으므로 클래스를 로드하는 기능은 가상 머신에 속하므로 가상 머신은 자체 ClassLoad를 통해 싱글톤 클래스를 로드할 때 클래스의 인스턴스를 생성합니다. Java 언어에서 이러한 동작은 두 가지 주요 이점을 가져올 수 있습니다. 1. 자주 사용되는 객체의 경우 객체 생성에 소요되는 시간을 생략할 수 있습니다. 이는 중량 객체에 대한 시스템 오버헤드가 매우 큽니다. 2. 새로운 작업 수가 많기 때문입니다. 감소하면 시스템 메모리 사용 빈도도 줄어들어 GC 압력이 감소합니다.
