Warum ist HashMap containsKey langsamer als in Sun JDK? (sun-jdk-1.6.0.17)

8

Warum ruft containsKey auf einer HashMap langsamer auf als get ?

Test: Ссылка (& gt; 15% Unterschied, laufen auf sun-jdk-1.6.0.17)

    
Stefan 03.11.2011, 17:48
quelle

4 Antworten

10

Weil es [etwas mehr] mehr Arbeit leistet, siehe die OpenJDK 7-Quelle .

Beachten Sie, dass containsKey getEntry aufruft, während get direkt "magic lookup" durchführt. Ich weiß nicht, warum es auf diese Weise gemacht wurde, und bin noch mehr verwirrt über die Verwendung / Nichtnutzung von getForNullKey : Siehe John Bs und Ted Hopps Kommentare, warum das so ist.

>

get hat eine frühe Codeaufteilung für einen Nullschlüssel (beachten Sie, dass get null zurückgibt, wenn der Eintrag nicht existiert oder mit einem gespeicherten Nullwert existiert):

%Vor%

Während getEntry , aufgerufen von containsKey , nicht in getForNullKey aufgeteilt wird, gibt es hier zusätzliche Arbeit, um nach dem Nullschlüssel-Fall zu suchen (für jeden in der Kette gescannten Eintrag):

%Vor%

Außerdem hat containsKey den zusätzlichen Bedingungs- und Methodenaufruf (beachten Sie, dass getEntry ein Entry-Objekt zurückgibt, wenn der Schlüssel existiert, auch wenn der gespeicherte Wert null ist):

%Vor%

Ich vermute, es könnte argumentiert werden, dass containsKey - in Bezug auf "Leistung" - von einem spezialisierten Formular profitieren würde (auf Kosten von weniger DRY-Code), oder dass getEntry dem Vorsprung von% folgen könnte co_de% mit einem frühen Null-Schlüssel-Check .. andererseits könnte man argumentieren, dass get in get geschrieben werden sollte; -)

Glückliche Kodierung.

    
user166390 03.11.2011, 17:51
quelle
3

Sehen wir uns den Quellcode an:

%Vor%

Vielleicht liegt es an dem zusätzlichen Methodenaufruf oder an der wiederholten Überprüfung auf key != null ?

    
Mehrdad 03.11.2011 17:53
quelle
3

Ich habe noch nicht versucht, Ihre Ergebnisse zu reproduzieren, aber meine erste Vermutung ist, dass get einfach den Wert (falls vorhanden) zurückgibt, der gefunden wurde, während containsKey (was Sie getestet haben, nicht contains ) muss getestet werden, ob der Schlüssel existiert (entweder mit einem Null- oder Nicht-Null-Wert) und dann einen booleschen Wert zurückgibt. Nur ein wenig mehr Aufwand beteiligt.

    
Ted Hopp 03.11.2011 17:52
quelle
3

Beim Testen verschiedener Größen von hashmaps ist, wenn es eine Verzerrung in der Leistung gibt, diese sehr klein.

Wird auf Java 7 Update 1 mit einem 4,6 GHz i7 2600K ausgeführt.

%Vor%

druckt für halbe Millionen Tasten

%Vor%

druckt für eine Million Tasten

%Vor%

jedoch für zwei Millionen Schlüssel

%Vor%

für fünf Millionen Schlüssel

%Vor%

BTW: Die Zeitkomplexität für get () und containsKey ist O (1) (auf einer idealisierten Maschine), aber Sie können sehen, dass für eine echte Maschine die Kosten mit der Größe der Map steigen.

    
Peter Lawrey 04.11.2011 08:10
quelle

Tags und Links