2017-01-17 4 views
9

Beim Erstellen eines HashSet und eines LinkedHashSet aus einer Sammlung wird der Wert initialCapacity in der Standardimplementierung auf andere Werte gesetzt.Unterschiedlicher Standardwert 'initialCapacity' HashSet und LinkedHashSet

HashSet:

public HashSet(Collection<? extends E> c) { 
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); 
    addAll(c); 
} 

LinkedHashSet:

public LinkedHashSet(Collection<? extends E> c) { 
    super(Math.max(2*c.size(), 11), .75f, true); 
    addAll(c); 
} 

Ich bin sicher, dass es ein ganz triftiger Grund dafür ist, aber ich kann nicht, es zu sehen.

+0

Bitte die Dokumentation lesen, bevor Sie Fragen hier posten: 'Eine verknüpfte Hash-Set verfügt über zwei Parameter, die Einfluss auf die Leistung: Anfangskapazität und Ladefaktor. Sie sind genau wie für HashSet definiert. Beachten Sie jedoch, dass die Strafe für die Wahl eines zu hohen Werts für die Anfangskapazität für diese Klasse weniger streng ist als für HashSet, da die Iterationszeiten für diese Klasse von der Kapazität nicht beeinflusst werden. "- https://docs.oracle.com/ javase/7/docs/api/java/util/LinkedHashSet.html –

+0

@TimBiegeleisen Ich wusste nicht, dass ich in den Kommentaren nicht Enter drücken konnte. –

+0

Info: 'HashSet' verwendet das Größere von' 4/3' der Größe oder '16', während' LinkedHashSet' das Größere der doppelten Größe oder '11' verwendet. Beide verwenden einen Auslastungsfaktor von '0,75f'. –

Antwort

4

Aus dem Code, den Sie uns gezeigt, hier sind die Spezifikationen für HashSet und LinkedHashSet:

data structure | initial capacity  | load factor 
HashSet  | max(1.333 * size, 16) | 0.75 
LinkedHashSet | max(2 * size, 11)  | 0.75 

Aus der Spitze von meinem Kopf, es teurer ist wahrscheinlich eine LinkedHashSet als ein einfaches HashSet wieder aufzuwärmen, wie die Der ehemalige hat eine verknüpfte Liste, die auch neu strukturiert werden muss. Wenn wir die Anfangskapazität erhöhen, könnten wir die anfängliche Kapazität für einige typische Anwendungsfälle nicht überschreiten.

Wenn die Anfangskapazität einer Hashtabellen-Datenstruktur in Java überschritten wird, muss sie erweitert werden. Dies erfordert unter anderem, dass jeder Eintrag in der Tabelle zu einem neuen Bucket aufgeräumt werden muss. Die Kosten dafür sollten ungefähr gleich sein, sowohl in LinkedHashSet als auch in HashSet. Jedoch hat eine LinkedHashSet eine zusätzliche Anforderung, wenn die Kapazität erweitert wird, da es eine verknüpfte Liste verwaltet, die die Einträge durchläuft. Diese Liste muss möglicherweise auch in dem Prozess neu strukturiert werden. Daher würde ich erwarten, dass die Kosten für die Kapazitätserweiterung in LinkedHashSet höher liegen als in HashSet. Indem wir LinkedHashSet eine größere Anfangskapazität geben, können wir diese kostspielige Kapazitätserweiterung für eine längere Zeit vermeiden.

LinkedHashSet Javadoc

+0

Das klingt vernünftig.Aber wenn diese Annahme richtig ist, sollte ich mich nicht auf die Standardwerte verlassen, wenn ich ein LinkedHashSet aus einer Collection für schreibgeschützte Zwecke konstruiere, besonders wenn die Collection sehr groß ist. – marthursson

+0

Können Sie Ihre Frage mit den Anwendungsfällen ("read-only"), die Sie im Sinn haben, aktualisieren? –

+0

Ist das nicht nur eine Randnotiz? In Anbetracht dessen, dass ich mich darüber gewundert habe, ist es nicht offensichtlich, dass der Nur-Lese-Zweck eine gültige Information ist :) – marthursson