java - 다중 HashMap과 Hashtable의 차이점은 무엇입니까?



15 Answers

많은 해답은 Hashtable이 동기화되어 있음을 나타냅니다. 실제로 이것은 거의 당신을 사지 않습니다. 액세서 / 뮤 테이타 메소드의 동기화는지도에서 동시에 추가하거나 제거하는 두 개의 스레드를 중지하지만 현실 세계에서는 종종 추가 동기화가 필요합니다.

매우 일반적인 관용구는 "확인한 다음"넣는 것입니다 - 즉, 맵에서 항목을 찾고 이미 존재하지 않으면 추가하십시오. 이것은 Hashtable 또는 HashMap을 사용하는 어떤 방식 으로든 원자 연산이 아닙니다.

등가 적으로 동기화 된 HashMap은 다음을 통해 얻을 수 있습니다.

Collections.synchronizedMap(myMap);

그러나이 논리를 올바르게 구현하려면 다음과 같은 형식의 추가 동기화 가 필요합니다.

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

Hashtable의 엔트리 (또는 Collections.synchronizedMap에 의해 취득 된 HashMap)를 반복해도 (자), 추가적인 동기화에 의해 맵이 변경되지 않는 한, thread로부터는 안전하지 않습니다.

ConcurrentMap 인터페이스 (예 : ConcurrentHashMap )의 구현은 다음 ConcurrentMap 같은 스레드 안전성 검사 - 실행 - 의미 체계를 포함하여이 중 일부를 해결합니다.

ConcurrentMap.putIfAbsent(key, value);
hashmap 동기화

Java에서 HashMapHashtable 의 차이점은 무엇입니까?

비 스레드 응용 프로그램에 더 효율적인 방법은 무엇입니까?




이 질문은 종종 인터뷰에서 후보자가 수집 수업의 올바른 사용법을 이해하고 있는지 확인하고 사용 가능한 대체 해결책을 알고 있는지 확인합니다.

  1. HashMap 클래스는 Hashtable과 거의 동일하지만, 동기화되지 않고 null을 허용한다는 점만 다릅니다. (HashMap은 null 값을 키와 값으로 허용하지만 Hashtable은 null을 허용하지 않습니다.)
  2. HashMap는지도의 순서가 시간이 지남에 따라 일정하게 유지 될 것이라고 보장하지 않습니다.
  3. HashMap은 동기화되지 않지만 HashTable은 동기화됩니다.
  4. HashMap의 Iterator는 Hashtable의 열거자가없는 동안은 안전합니다. 다른 Thread가 Iterator 자신의 remove () 메소드를 제외한 요소를 추가하거나 제거하여 구조적으로 맵을 수정하면 ConcurrentModificationException을 던집니다. 그러나 이것은 보장 된 행동이 아니며 최선의 노력을 기울여 JVM에 의해 수행됩니다.

몇몇 중요한 기간에 주

  1. 동기화 됨은 하나의 스레드 만이 한 시점에서 해시 테이블을 수정할 수 있음을 의미합니다. 기본적으로, 해시 테이블에서 업데이트를 수행하기 전에 모든 스레드가 객체에 대한 잠금을 획득해야하고 다른 스레드는 잠금을 해제 할 때까지 대기해야 함을 의미합니다.
  2. 페일 세이프는 반복자의 컨텍스트와 관련이 있습니다. 반복자가 콜렉션 객체로 작성되어 다른 thread가 「구조적으로」콜렉션 객체를 변경하려고하면 (자), 병행 변경 예외가 Throw됩니다. 그러나 "구조적으로"컬렉션을 수정하지 않으므로 다른 스레드가 "set"메서드를 호출 할 수 있습니다. 다만, 「set」를 호출하기 전에, 컬렉션이 구조적으로 변경되었을 경우는, 「IllegalArgumentException」가 Throw됩니다.
  3. 구조적으로 수정이란지도의 구조를 효과적으로 변경할 수있는 요소를 삭제하거나 삽입하는 것을 의미합니다.

HashMap은 다음과 같이 동기화 할 수 있습니다.

Map m = Collections.synchronizeMap(hashMap);

Map는 Enumeration 객체를 통해 반복을 직접 지원하는 대신 Collection 뷰를 제공합니다. 컬렉션 뷰는이 섹션의 뒷부분에서 설명하는 것처럼 인터페이스의 표현력을 크게 향상시킵니다. 지도를 사용하면 키, 값 또는 키 - 값 쌍을 반복 할 수 있습니다. Hashtable은 세 번째 옵션을 제공하지 않습니다. Map은 반복되는 동안 엔트리를 제거하는 안전한 방법을 제공합니다. Hashtable은 그렇지 않았습니다. 마지막으로 Map은 Hashtable 인터페이스의 사소한 결점을 수정합니다. Hashtable에는 contains라는 메서드가 있는데, Hashtable에 지정된 값이 들어 있으면 true를 반환합니다. 그 이름이 주어지면 (자), Hashtable가 Hashtable의 주 액세스기구이기 (위해) 때문에, Hashtable가 지정된 키를 포함한 경우에,이 메소드가 true를 돌려 줄 것을 기대할 수 있습니다. Map 인터페이스는 containsValue 메소드의 이름을 변경함으로써 혼란의 근원을 제거합니다. 또한 이것은 인터페이스의 일관성을 향상시킵니다 - containsValue parallel contains containsKey.

맵 인터페이스




HashTable 은 JCF (Java Collections Framework)가 도입되기 전에 레거시 클래스였으며 Map 인터페이스를 구현하기 위해 나중에 개조되었습니다. VectorStack .

그러므로 다른 사람들이 지적했듯이 항상 JCF에서 더 나은 대안이 있기 때문에 언제나 새로운 코드로 그들과 떨어져 있어야 합니다.

유용한 자바 컬렉션 치트 시트 는 다음과 같습니다. 회색 블록에는 레거시 클래스 HashTable, Vector 및 Stack이 포함되어 있습니다.




이 도표를보십시오. HashMap 및 Hashtable과 함께 다른 데이터 구조 간의 비교를 제공합니다. 비교는 정확하고 명확하며 이해하기 쉽습니다.

Java Collection Matrix




이미 많은 좋은 답변이 게시되어 있습니다. 몇 가지 새로운 점을 추가하고 요약합니다.

HashMapHashtable 은 키와 값 형식으로 데이터 를 저장하는 데 사용됩니다. 둘 다 고유 키를 저장하기 위해 해싱 기술을 사용하고 있습니다. 그러나 아래에 주어진 HashMap과 Hashtable 클래스에는 많은 차이점이 있습니다.

HashMap

  1. HashMap 은 동기화되지 않습니다. 그것은 스레드가 안전하지 않으며 적절한 동기화 코드가없는 여러 스레드간에 공유 될 수 없습니다.
  2. HashMap 은 하나의 널 (null) 키와 복수의 널값을 허용합니다.
  3. HashMap 은 JDK 1.2에서 소개 된 새로운 클래스입니다.
  4. HashMap 이 빠릅니다.
  5. 이 코드를 호출하여 HashMap 을 동기화 된 상태로 만들 수 있습니다.
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap 은 Iterator에 의해 트래버스됩니다.
  7. HashMap Iterator는 fail-fast입니다.
  8. HashMap AbstractMap 클래스를 상속받습니다.

Hashtable

  1. Hashtable 이 동기화됩니다. 스레드로부터 안전하며 많은 스레드와 공유 할 수 있습니다.
  2. Hashtable 은 null 키 또는 값을 허용하지 않습니다.
  3. Hashtable 은 레거시 클래스입니다.
  4. Hashtable 이 느립니다.
  5. Hashtable 은 내부적으로 동기화되어 있으므로 동기화 할 수 없습니다.
  6. Hashtable 은 Enumerator와 Iterator에 의해 트래버스됩니다.
  7. Hashtable 열거자는 실패하지 않습니다.
  8. Hashtable Dictionary 클래스를 상속받습니다.

추가 정보 Java의 HashMap과 Hashtable의 차이점은 무엇입니까?




이미 언급 한 다른 중요한 측면과 더불어 Collections API (예 : Map 인터페이스)는 Java 스펙에 대한 "최신의 최고의"추가 사항을 준수하도록 항상 수정되고 있습니다.

예를 들어 Java 5 Map iterating :

for (Elem elem : map.keys()) {
  elem.doSth();
}

이전 Hashtable 접근 방식과 비교 :

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

Java 1.8에서 우리는 오래된 스크립트 언어처럼 HashMap을 구성하고 액세스 할 수 있다고 약속합니다.

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

업데이트 : 아니오, 그들은 1.8에 착륙하지 않습니다 ... :(

Project Coin의 컬렉션 향상 기능이 JDK8에 포함될 예정입니까?




HashMapHashtable 은 중요한 알고리즘상의 차이점이 있습니다. 전에 아무도이 사실을 언급하지 않았습니다. 그래서 그것을 가져오고 있습니다. HashMap 은 두 크기의 해시 테이블을 생성하고 동적으로 증가시켜 모든 버킷에서 약 8 개의 요소 (충돌)를 가지며 일반 요소 유형에 대해 요소를 매우 잘 저어줍니다. 그러나 Hashtable 구현은 Hashtable 보다 잘 제어 할 수있게 해줍니다. 예를 들어, 가장 가까운 소수를 값 도메인 크기로 사용하여 테이블 크기를 수정할 수 있습니다. 이렇게하면 HashMap보다 성능이 향상됩니다. 충돌을 일으킬 수 있습니다.

이 질문에서 광범위하게 논의 된 분명한 차이점과는 달리 Hashtable은 해시를보다 잘 제어 할 수있는 "수동 드라이브"자동차로, 일반적으로 잘 작동하는 "자동 드라이브"로 HashMap을 사용합니다.




here 에 정보를 기반으로, 나는 HashMap 함께가는 것이 좋습니다거야. 가장 큰 장점은 iterator를 통해 반복하지 않는 한 Java가 반복하는 동안 자바가 수정하지 못하게한다는 것입니다.




Collection 때때로 컨테이너라고도 함)은 단순히 여러 요소를 단일 단위로 그룹화하는 객체입니다. Collection 은 집계 데이터를 저장, 검색, 조작 및 전달하는 데 사용됩니다. 컬렉션 프레임 워크 W 는 컬렉션을 나타내고 조작하기위한 통일 ​​된 아키텍처입니다.

HashMap JDK1.2 와 Hashtable JDK1.0 은 모두 <Key, Value> 쌍으로 표현되는 객체 그룹을 나타내는 데 사용됩니다. 각 <Key, Value> 쌍을 Entry 객체라고합니다. Entry 컬렉션은 HashMapHashtable 의 객체에 의해 참조됩니다. 컬렉션의 키는 고유하거나 고유해야합니다. [매핑 된 값에 특정 키를 검색하는 데 사용됩니다. 컬렉션의 값을 복제 할 수 있습니다.]

« 수퍼 클래스, 레거시 및 콜렉션 Framework 멤버

Hashtable은 Dictionary 클래스의 서브 클래스 인 JDK1.0 에서 소개 된 레거시 클래스입니다. JDK1.2 Hashtable은 Map 인터페이스 를 구현하여 컬렉션 프레임 워크의 멤버가되도록 다시 엔지니어링되었습니다. HashMap은 JDK1.2 에서 처음 소개 된 시점부터 Java Collection Framework의 멤버입니다. HashMap는 AbstractMap 클래스의 서브 클래스입니다.

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

« 초기 용량 및 부하율

용량은 해시 테이블의 버킷 수이며 초기 용량은 단순히 해시 테이블을 만들 때의 용량입니다. 해시 테이블은 열려 있습니다. " hash collision "의 경우 단일 버킷은 여러 항목을 저장하므로 순차적으로 검색해야합니다. 부하 계수는 용량이 자동으로 증가하기 전에 해시 테이블이 얼마나 채워지는지 측정합니다.

HashMap는 디폴트의 초기 용량 (16) 과 디폴트의 부하 계수 (0.75)로 하늘의 해시 테이블을 구축합니다. Hashtable가 디폴트의 초기 용량 (11) 과 부하 계수 / 기입 비율 (0.75)로 하늘의 해시 테이블을 구축하는 것에 따라,

« 해시 충돌의 경우 구조적 수정

HashMap , Hashtable 해시 충돌의 경우지도 항목을 연결된 목록에 저장합니다. 해시 버킷이 특정 임계 값을 초과하면 HashMap 용 Java8 에서 해당 버킷이 linked list of entries to a balanced tree 됩니다. O (n)에서 O (log n)까지의 최악의 성능을 향상시킵니다. 목록을 이진 트리로 변환하는 동안 해시 코드는 분기 변수로 사용됩니다. 같은 버킷에 2 개의 다른 해시 코드가있는 경우, 1 개는 큰 것으로 간주되어 트리의 오른쪽으로, 다른 1 개는 왼쪽으로 이동합니다. 그러나 두 해시 코드가 같은 경우 HashMap 은 키가 서로 비슷하다고 가정하고 키를 비교하여 방향을 결정하므로 일부 순서를 유지할 수 있습니다. HashMap 의 키를 comparable 하게 만드는 것이 좋습니다. 버킷 크기가 TREEIFY_THRESHOLD = 8 도달하면 항목을 추가하여 연결된 트리 목록으로 변환합니다. TREEIFY_THRESHOLD 보다 TREEIFY_THRESHOLD 거나 최대 UNTREEIFY_THRESHOLD = 6 항목을 제거하면 균형 트리가 연결된 항목 목록으로 변환됩니다. Java 8 SRC , stackpost

« 콜렉션 뷰 반복, Fail-Fast 및 Fail-Safe

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iterator 는 본질 상 패스트 패스트입니다. 즉, 자신 만의 remove () 메소드 이외의 반복 처리 중에 컬렉션이 수정되었을 경우, ConcurrentModificationException를 Throw합니다. Enumeration 이 사실상 fail-safe 인 곳 iterating하는 동안 컬렉션이 수정되면 예외를 throw하지 않습니다.

Java API Docs에 따르면, Iterator는 항상 Enumeration보다 선호됩니다.

참고 : Enumeration 인터페이스의 기능은 Iterator 인터페이스에 의해 복제됩니다. 또한 Iterator는 선택적 remove 연산을 추가하고 메소드 이름이 더 짧습니다. 새로운 구현에서는, Enumeration보다 Iterator를 사용하는 것을 고려할 필요가 있습니다.

Java 5에서 도입 된 ConcurrentMap 인터페이스 : ConcurrentHashMap - 해시 테이블에 의해 뒷받침되는 ConcurrentMap 가 가능한 고성능 ConcurrentMap 구현입니다. 이 구현은 검색을 수행 할 때 결코 차단되지 않으며 클라이언트가 업데이트의 동시성 수준을 선택할 수 있습니다. 이것은 Hashtable 의 드롭 인 대체품입니다 : ConcurrentMap 을 구현하는 것 외에도, Hashtable 고유 한 모든 "레거시"메소드를 지원합니다.

  • HashMapEntry 의 값은 volatile 이므로 수정 된 수정과 후속 읽기에 대한 미세한 입자 일관성을 보장합니다. 각 읽기는 가장 최근에 완료된 업데이트를 반영합니다.

  • 반복자와 열거 형은 반복자 / 열거 형의 생성 이후 어떤 시점에서 상태를 반영하는 Fail Safe입니다. 이를 통해 일관성을 유지하면서 읽기 및 수정을 동시에 수행 할 수 있습니다. 그들은 ConcurrentModificationException을 throw하지 않습니다. 그러나 이터레이터는 한 번에 하나의 스레드에서만 사용하도록 설계되었습니다.

  • Hashtable 와 같지만 HashMap 과 달리이 클래스는 null을 키 또는 값으로 사용할 수 없습니다.

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();

    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.

                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }

                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */

                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();

    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

« Null 키와 Null 값

HashMap 은 최대 하나의 널 (NULL) 키와 임의의 수의 널값을 허용합니다. Hashtable 가 단일 null 키와 null 값도 허용하지 않는 경우, 키 또는 값 null이 있으면 NullPointerException을 발생시킵니다. Example

« 동기, 스레드 안전

Hashtable 은 내부적으로 동기화됩니다. 따라서 다중 스레드 응용 프로그램에서 Hashtable 을 사용하는 것이 매우 안전합니다. HashMap 가 내부적으로 동기화되지 않은 곳. 따라서 외부 동기화없이 다중 스레드 응용 프로그램에서 HashMap 을 사용하는 것은 안전하지 않습니다. Collections.synchronizedMap() 메서드를 사용하여 HashMap 을 외부에서 동기화 할 수 있습니다.

« 성능

Hashtable 은 내부적으로 동기화되기 때문에 Hashtable HashMap 보다 약간 느리게 만듭니다.

@만나다




1. HashmapHashTable 모두 키와 값을 저장합니다.

2. Hashmap 은 하나의 키를 null 로 저장할 수 있습니다. Hashtablenull 저장할 수 없습니다.

3. HashMap 은 동기화되지 않지만 Hashtable 은 동기화됩니다.

4. HashMapCollection.SyncronizedMap(map) 과 동기화 될 수 있습니다.

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);



내 작은 기여 :

  1. 첫째 사이 다른 가장 중요 Hashtable하고 HashMap있다는 것입니다 HashMap스레드로부터 안전하지 않습니다 동안은 Hashtable스레드 안전 모음입니다.

  2. 사이 두 번째로 중요한 차이점 Hashtable하고 HashMap있기 때문에, 성능입니다 HashMap그것보다 더 잘 수행 동기화되지 않습니다 Hashtable.

  3. 에 세 번째 차이 Hashtable대는 HashMapHashtable사용되지 않는 클래스와 사용되어야한다 ConcurrentHashMap대신에 Hashtable자바있다.




1) Hashtable은 동기화되지만 hashmap은 동기화되지 않습니다. 2) 또 다른 차이점은 HashMap의 반복자는 오류 방지이며 Hashtable의 열거자는 그렇지 않다는 것입니다. 반복하는 동안지도를 변경하면 알게됩니다.

3) HashMap은 null 값을 허용하지만 Hashtable은 null 값을 허용합니다.




Hashtable:

Hashtable 은 키 - 값 쌍의 값을 유지하는 데이터 구조입니다. 키와 값 모두에 대해 null을 허용하지 않습니다. NullPointerExceptionnull 값을 추가 하면 a를 얻을 수 있습니다. 그것은 동기화됩니다. 따라서 비용이 발생합니다. 한 스레드 만 특정 시간에 HashTable 에 액세스 할 수 있습니다 .

:

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

HashMap :

HashMapHashtable 과 비슷 하지만 키 값 쌍을 허용합니다. 키와 값 모두에 대해 null을 허용합니다. 더 나은 성능보다 더 나은 HashTable것이 때문에 unsynchronized.

예:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}



HashMaps는 당신에게 동기화의 자유를 주며, 디버깅은 훨씬 더 쉽습니다.




동기화 또는 스레드 안전 :

해시 맵은 동기화되지 않으므로 안전하지 않으며 적절하게 동기화 된 블록이 없으면 여러 스레드간에 공유 될 수 없지만 Hashtable은 동기화되므로 스레드로부터 안전합니다.

Null 키 및 Null 값 :

HashMap은 하나의 null 키와 임의의 수의 null 값을 허용합니다. Hashtable은 null 키 또는 값을 허용하지 않습니다.

값 반복 :

HashMap의 Iterator는, 패스트 패스트 반복자입니다 만, Hashtable의 열거자는 존재하지 않습니다. 다른 thread가 Iterator 자신의 remove () 메소드 이외의 요소를 추가 또는 삭제하는 것에 의해, 구조적으로 맵을 변경하는 경우, ConcurrentModificationException를 슬로우합니다.

수퍼 클래스 및 레거시 :

HashMap은 AbstractMap 클래스의 하위 클래스이고 Hashtable은 Dictionary 클래스의 하위 클래스입니다.

실적 :

HashMap은 동기화되지 않으므로 HashTable에 비해 빠릅니다.

자바 컬렉션과 관련된 예제와 인터뷰 질문 및 퀴즈는 http://modernpathshala.com/Article/1020/difference-between-hashmap-and-hashtable-in-java 를 참조하십시오 http://modernpathshala.com/Article/1020/difference-between-hashmap-and-hashtable-in-java




Related