{"id":96,"date":"2023-12-19T10:58:51","date_gmt":"2023-12-19T09:58:51","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=96"},"modified":"2024-01-08T09:12:54","modified_gmt":"2024-01-08T08:12:54","slug":"java-hashmap-interna-buckets-capacity-load-factor-und-collisions","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=96","title":{"rendered":"Java HashMap Interna &#8211; Buckets, Capacity, Load Factor und Collisions"},"content":{"rendered":"\n<p>Java HashMap ist eine der h\u00e4ufigsten Datenstrukturen, die in der Java-Programmierung verwendet werden, um Schl\u00fcssel-Wert-Paare effizient zu speichern und abzurufen. Um die Interna von Java HashMaps zu verstehen, m\u00fcssen wir einige grundlegende Begriffe wie Hashing, Buckets, Capacity, Load Factors und Collisions verstehen. Dar\u00fcber hinaus werden wir den Vorgang des Rehashings besprechen und wie man es in F\u00e4llen gro\u00dfer HashMaps durch passende Wahl der Initial Capacity vermeiden kann.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hashing und die Bedeutung von Hash Codes<\/h2>\n\n\n\n<p>Das Herzst\u00fcck einer HashMap ist die Hash-Funktion. Eine Hash-Funktion ist eine Methode, die einen Eingabewert, in diesem Fall den Schl\u00fcssel, in einen numerischen Wert, den Hash-Code, umwandelt. Dieser Hash-Code dient als Index, um den entsprechenden Wert in der HashMap schnell abzurufen. Die Qualit\u00e4t der Hash-Funktion ist entscheidend, um die Effizienz der HashMap sicherzustellen. Idealerweise sollte die Hash-Funktion sicherstellen, dass Schl\u00fcssel gleichm\u00e4\u00dfig \u00fcber die verf\u00fcgbaren Speicherbereiche verteilt werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Buckets und Capacity<\/h2>\n\n\n\n<p>In einer HashMap werden Schl\u00fcssel-Wert-Paare in sogenannten &#8222;Buckets&#8220; gespeichert. Buckets sind in der Regel Arrays oder Listen, die dazu dienen, Schl\u00fcssel-Wert-Paare zu gruppieren, die denselben Hash-Code haben. Die HashMap verf\u00fcgt \u00fcber eine bestimmte Anzahl von Buckets, die als Capacity bezeichnet wird. Die Kapazit\u00e4t ist zu Beginn der Erstellung einer HashMap festgelegt und bestimmt die maximale Anzahl von Buckets, die die HashMap halten kann.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Load Factors und die Auswirkungen auf die Leistung<\/h2>\n\n\n\n<p>Der Load Factor ist ein Wert zwischen 0 und 1, der angibt, wie voll die HashMap ist. Er wird berechnet, indem die Anzahl der in der HashMap gespeicherten Schl\u00fcssel-Wert-Paare durch die Kapazit\u00e4t der HashMap geteilt wird. Wenn der Load Factor hoch ist, bedeutet dies, dass die HashMap fast voll ist, und wenn er niedrig ist, gibt es noch viel Platz in der HashMap.<\/p>\n\n\n\n<p>Ein hoher Load Factor f\u00fchrt zu einer geringeren Leistung der HashMap, da die Wahrscheinlichkeit von Kollisionen (dazu sp\u00e4ter mehr) steigt. Um dies zu vermeiden, ist es wichtig, den Load Factor im Auge zu behalten und gegebenenfalls die Kapazit\u00e4t der HashMap anzupassen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Collisions: Das Problem der Hash-Kollisionen<\/h2>\n\n\n\n<p>Eine Hash-Kollision tritt auf, wenn zwei verschiedene Schl\u00fcssel denselben Hash-Code erzeugen. Dies kann vorkommen, da die meisten Hash-Funktionen eine begrenzte Anzahl von m\u00f6glichen Hash-Codes haben, w\u00e4hrend es unendlich viele m\u00f6gliche Schl\u00fcssel gibt. Wenn eine Kollision auftritt, muss die HashMap eine Strategie zur Bew\u00e4ltigung dieser Situation haben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Rehashing: Die L\u00f6sung f\u00fcr Kollisionen<\/h2>\n\n\n\n<p>Rehashing ist der Prozess, bei dem die HashMap ihre Kapazit\u00e4t erh\u00f6ht und alle Schl\u00fcssel-Wert-Paare in die neuen Buckets umverteilt, um Kollisionen zu vermeiden. Dies ist notwendig, wenn der Load Factor zu hoch wird und die HashMap ineffizient wird.<\/p>\n\n\n\n<p>Rehashing erfolgt normalerweise automatisch in der HashMap, wenn der Load Factor einen bestimmten Schwellenwert \u00fcberschreitet. W\u00e4hrend des Rehashing wird die Kapazit\u00e4t der HashMap erh\u00f6ht, und alle Schl\u00fcssel-Wert-Paare werden neu gehasht und in die entsprechenden Buckets verschoben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wann passiert Rehashing und seine Auswirkungen<\/h2>\n\n\n\n<p>Rehashing tritt auf, wenn der aktuelle Load Factor den vordefinierten Schwellenwert \u00fcberschreitet. In Java 8 betr\u00e4gt dieser Schwellenwert in der HashMap etwa 0,75 (75%). Das bedeutet, dass, wenn die Anzahl der gespeicherten Schl\u00fcssel-Wert-Paare 75% der Kapazit\u00e4t der HashMap erreicht, ein Rehashing ausgel\u00f6st wird.<\/p>\n\n\n\n<p>Die Auswirkungen von Rehashing sind in der Regel:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Leistungseinbu\u00dfen<\/strong>: W\u00e4hrend des Rehashing-Prozesses wird die gesamte HashMap neu organisiert, was zu einer vor\u00fcbergehenden Verschlechterung der Leistung f\u00fchren kann. Dieser Prozess kann einige Zeit in Anspruch nehmen, insbesondere bei gro\u00dfen HashMaps.<\/li>\n\n\n\n<li><strong>Speicherplatzverbrauch<\/strong>: Nach dem Rehashing wird die Kapazit\u00e4t der HashMap erh\u00f6ht, was zu einem h\u00f6heren Speicherbedarf f\u00fchrt. Es ist wichtig sicherzustellen, dass gen\u00fcgend Speicherplatz verf\u00fcgbar ist, um das Rehashing durchzuf\u00fchren.<\/li>\n\n\n\n<li><strong>Bessere Leistung nach Rehashing<\/strong>: Nachdem das Rehashing abgeschlossen ist, sollten Kollisionen reduziert und die HashMap wieder effizienter sein.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Vermeidung von unn\u00f6tigem Rehashing durch richtige Wahl der Initial Capacity<\/h2>\n\n\n\n<p>Um unn\u00f6tiges Rehashing zu vermeiden, ist es m\u00f6glich, die richtige Anfangskapazit\u00e4t (Initial Capacity) f\u00fcr die HashMap festzulegen. Eine zu niedrige Anfangskapazit\u00e4t kann dazu f\u00fchren, dass die HashMap h\u00e4ufiger neu organisiert werden muss, was die Leistung beeintr\u00e4chtigt. Eine zu hohe Anfangskapazit\u00e4t kann hingegen zu einem unn\u00f6tig hohen Speicherverbrauch f\u00fchren.<\/p>\n\n\n\n<p>Der Standardwert f\u00fcr die Capacity ist 16, und ausreichend f\u00fcr die allermeisten HashMaps. Die initialen Rehashings sind auch noch verh\u00e4ltnism\u00e4\u00dfig g\u00fcnstig, da wenige Werte in der Map liegen. Deswegen f\u00e4hrt man als Entwickler mit dem Vorgehen, f\u00fcr die meisten HashMaps keine eigene Anfangskapazit\u00e4t festzulegen, in der Regel gut. Aber: bei erwartbar gro\u00dfen Maps kann dies anders aussehen! Rehashing von zehntausenden von Werten ist wesentlich teurer als bei ein paar Dutzend Elementen und kann zu sp\u00fcrbarer Verz\u00f6gerung in der Reaktivit\u00e4t einer Anwendung f\u00fchren. Es ist daher bei erwartbar gro\u00dfen Maps ratsam, die Anfangskapazit\u00e4t manuell basierend auf der erwarteten Gr\u00f6\u00dfe der HashMap und dem Load Factor zu w\u00e4hlen. Eine grobe Faustregel ist, die Anfangskapazit\u00e4t so zu w\u00e4hlen, dass die HashMap etwa doppelt so viele Buckets hat, wie Sie erwarten, Schl\u00fcssel-Wert-Paare zu speichern. Dies hilft, unn\u00f6tiges Rehashing zu vermeiden und die HashMap effizient zu halten.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">int initialCapacity = <span class=\"hljs-number\">50000<\/span>; <span class=\"hljs-comment\">\/\/ Beispielsweise<\/span>\nfloat loadFactor = <span class=\"hljs-number\">0.75<\/span>f; <span class=\"hljs-comment\">\/\/ Standard in Java HashMap<\/span>\nHashMap&lt;KeyType, ValueType&gt; bigMap = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;(initialCapacity, loadFactor);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel wird eine gro\u00dfe HashMap mit einer Anfangskapazit\u00e4t von 50.000 und einem Load Factor von 0,75 erstellt. Dies sollte f\u00fcr eine gro\u00dfe Map, in der voraussichtlich bis zu etwa 30.000 Key-Value-Paare gespeichert werden sollen, ausreichen.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java HashMap ist eine der h\u00e4ufigsten Datenstrukturen, die in der Java-Programmierung verwendet werden, um Schl\u00fcssel-Wert-Paare effizient zu speichern und abzurufen. Um die Interna von Java HashMaps zu verstehen, m\u00fcssen wir einige grundlegende Begriffe wie Hashing, Buckets, Capacity, Load Factors und Collisions verstehen. Dar\u00fcber hinaus werden wir den Vorgang des Rehashings besprechen und wie man es [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-96","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/96","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=96"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/96\/revisions"}],"predecessor-version":[{"id":97,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/96\/revisions\/97"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=96"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=96"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=96"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}