A Collection
- manchmal auch Container genannt - ist einfach ein Objekt, das mehrere Elemente zu einer Einheit zusammenfasst. Collection
s werden zum Speichern, Abrufen, Bearbeiten und Kommunizieren aggregierter Daten verwendet. Ein Sammlungsframework W ist eine einheitliche Architektur zum Darstellen und Bearbeiten von Sammlungen.
Die HashMap
JDK1.2
und die Hashtabelle JDK1.0
werden beide verwendet, um eine Gruppe von Objekten darzustellen, die <Key, Value>
paarweise dargestellt werden. Jedes <Key, Value>
Paar heißt Entry
Objekt. Die Sammlung von Einträgen wird durch den Gegenstand von HashMap
und bezeichnet Hashtable
. Schlüssel in einer Sammlung müssen eindeutig oder unverwechselbar sein. [da sie verwendet werden, um einen zugeordneten Wert eines bestimmten Schlüssels abzurufen. Werte in einer Sammlung können dupliziert werden.]
« Mitglied des Superclass, Legacy and Collection Framework
Hashtable ist eine in eingeführte Legacy-Klasse JDK1.0
, die eine Unterklasse der Dictionary-Klasse ist. From JDK1.2
Hashtable wurde überarbeitet, um die Map-Schnittstelle zu implementieren und Mitglied des Collection-Frameworks zu werden. HashMap ist seit Beginn seiner Einführung in Java Collection Framework Mitglied JDK1.2
. HashMap ist die Unterklasse der AbstractMap-Klasse.
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 { ... }
« Anfangskapazität und Lastfaktor
Die Kapazität ist die Anzahl der Buckets in der Hash-Tabelle, und die anfängliche Kapazität ist einfach die Kapazität zum Zeitpunkt der Erstellung der Hash-Tabelle. Beachten Sie, dass die Hash-Tabelle geöffnet ist: Im Fall eines " hash
collision
" speichert ein einzelner Bucket mehrere Einträge, die nacheinander durchsucht werden müssen. Der Auslastungsfaktor ist ein Maß dafür, wie voll die Hash-Tabelle werden darf, bevor ihre Kapazität automatisch erhöht wird.
HashMap erstellt eine leere Hash-Tabelle mit der Standard-Anfangskapazität (16) und dem Standard-Ladefaktor (0,75). Wobei als Hashtable eine leere Hashtable mit einer Standard-Anfangskapazität (11) und einem Lastfaktor / Füll-Verhältnis (0,75) erstellt wird.
« Strukturänderung bei Hash-Kollision
HashMap
, Hashtable
Bei Hash - Kollisionen sie speichern die Map - Einträge in verknüpften Listen. Wenn in Java8 derHashMap
Hash-Bucket einen bestimmten Schwellenwert überschreitet, wechselt dieser Bucket von linked list of entries to a balanced tree
. die die Worst-Case-Leistung von O (n) auf O (log n) verbessern. Beim Konvertieren der Liste in einen Binärbaum wird Hashcode als Verzweigungsvariable verwendet. Wenn sich zwei verschiedene Hashcodes im selben Bucket befinden, wird einer als größer angesehen und befindet sich rechts vom Baum und der andere links. Wenn jedoch beide Hashcodes gleich sind, wird HashMap
davon ausgegangen, dass die Schlüssel vergleichbar sind, und der Schlüssel wird verglichen, um die Richtung zu bestimmen, damit eine bestimmte Reihenfolge beibehalten werden kann. Es ist eine gute Praxis, die Schlüssel HashMap
vergleichbar zu machen . Beim Hinzufügen von Einträgen, wenn die Bucket-Größe erreicht istTREEIFY_THRESHOLD = 8
Konvertieren Sie die verknüpfte Liste von Einträgen in einen ausgeglichenen Baum. Wenn Sie Einträge entfernen, die kleiner als TREEIFY_THRESHOLD
und höchstens sind, UNTREEIFY_THRESHOLD = 6
wird der ausgeglichene Baum wieder in eine verknüpfte Liste von Einträgen konvertiert . Java 8 SRC , Stackpost
« Iteration der Sammlungsansicht, ausfallsicher und ausfallsicher
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
Iterator
ist ein Fail-Fast in der Natur. Das heißt, es wird eine ConcurrentModificationException ausgelöst, wenn eine Sammlung geändert wird, während eine andere als die eigene remove () -Methode iteriert wird. Wo wie Enumeration
in der Natur ausfallsicher ist. Es werden keine Ausnahmen ausgelöst, wenn eine Sammlung während der Iteration geändert wird.
Laut Java API Docs wird Iterator immer der Aufzählung vorgezogen.
HINWEIS: Die Funktionalität der Enumeration-Schnittstelle wird von der Iterator-Schnittstelle dupliziert. Darüber hinaus fügt Iterator eine optionale Entfernungsoperation hinzu und verfügt über kürzere Methodennamen. Neue Implementierungen sollten die Verwendung von Iterator anstelle von Enumeration in Betracht ziehen.
In Java 5 wurde die ConcurrentMap-Schnittstelle eingeführt : ConcurrentHashMap
- Eine hochkonkurrierende, leistungsstarke ConcurrentMap
Implementierung, die von einer Hash-Tabelle unterstützt wird. Diese Implementierung wird beim Abrufen niemals blockiert und ermöglicht es dem Client, die Parallelitätsstufe für Aktualisierungen auszuwählen. Es ist als Ersatz für Folgendes gedacht Hashtable
: Zusätzlich zur Implementierung ConcurrentMap
unterstützt es alle "Legacy" -Methoden, die es gibt Hashtable
.
Jeder HashMapEntry
s-Wert ist flüchtig, wodurch eine feine Kornkonsistenz für konkurrierende Modifikationen und nachfolgende Lesevorgänge sichergestellt wird. Jeder Lesevorgang spiegelt das zuletzt abgeschlossene Update wider
Iteratoren und Aufzählungen sind ausfallsicher - spiegeln den Status zu einem bestimmten Zeitpunkt seit der Erstellung des Iterators / der Aufzählung wider. Dies ermöglicht gleichzeitiges Lesen und Ändern auf Kosten einer verringerten Konsistenz. Sie lösen keine ConcurrentModificationException aus. Iteratoren können jedoch jeweils nur von einem Thread verwendet werden.
Wie, Hashtable
aber HashMap
nicht, erlaubt diese Klasse nicht, dass Null als Schlüssel oder Wert verwendet wird.
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();
}
}
« Nullschlüssel und Nullwerte
HashMap
erlaubt maximal einen Nullschlüssel und eine beliebige Anzahl von Nullwerten. Wenn as Hashtable
nicht einmal einen einzelnen Nullschlüssel und einen Nullwert zulässt, wird, wenn der Schlüssel oder Wert Null ist, eine NullPointerException ausgelöst. Beispiel
« Synchronisiert, threadsicher
Hashtable
ist intern synchronisiert. Daher ist die Verwendung Hashtable
in Multithread-Anwendungen sehr sicher . Wobei as HashMap
nicht intern synchronisiert ist. Daher ist die Verwendung HashMap
in Multithread-Anwendungen ohne externe Synchronisierung nicht sicher . Sie können HashMap
mithilfe der Collections.synchronizedMap()
Methode extern synchronisieren .
« Leistung
Da Hashtable
intern synchronisiert, macht dies Hashtable
etwas langsamer als die HashMap
.
@Sehen