86 Stimmen

Behält HashSet die Einfügereihenfolge bei?

Ist die HashSet Sammlung, die in .NET 3.5 eingeführt wurde, behält die Einfügereihenfolge bei, wenn die Iteration mit foreach ?

El Dokumentation besagt, dass die Sammlung nicht sortiert ist, aber sie sagt nichts über die Einfügereihenfolge aus. Eine Vorabversion der BCL Blogeintrag besagt, dass sie ungeordnet ist, aber dieser Artikel besagt, dass die Einfügereihenfolge beibehalten werden soll. Meine begrenzten Tests deuten darauf hin, dass die Reihenfolge beibehalten wird, aber das könnte ein Zufall sein.

1 Stimmen

Auf meinem Computer new HashSet<int>() { 6, 8 }.ToList() liefert [6,8], aber new HashSet<int>() { 8, 6 }.ToList() Rückgabe [8,6]

0 Stimmen

Dies könnte durch folgende Lektüre erklärt werden github.com/dotnet/corefx/blob/master/src/System.Collections/src/

0 Stimmen

Falls Sie eine solche Sammlung benötigen, schauen Sie sich diese an: github.com/OndrejPetrzilka/Rock.Collections

93voto

Michael Burr Punkte 320591

Diese HashSet MSDN-Seite sagt ausdrücklich:

Eine Menge ist eine Sammlung, die keine doppelten Elemente enthält und deren Elemente in keiner bestimmten Reihenfolge angeordnet sind.

54voto

Jon Skeet Punkte 1325502

Ich denke, der Artikel, in dem behauptet wird, dass die Reihenfolge erhalten bleibt, ist schlichtweg falsch. Bei einfachen Tests kann die Einfügereihenfolge aufgrund der internen Struktur durchaus erhalten bleiben, aber das ist nicht garantiert und wird auch nicht immer so funktionieren. Ich werde versuchen, ein Gegenbeispiel zu finden.

EDIT: Hier ist das Gegenbeispiel:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        var set = new HashSet<int>();

        set.Add(1);
        set.Add(2);
        set.Add(3);
        set.Remove(2);
        set.Add(4);

        foreach (int x in set)
        {
            Console.WriteLine(x);
        }
    }
}

Es wird 1, 4, 3 gedruckt, obwohl 3 vor 4 eingefügt wurde.

Es ist möglich dass die Einfügereihenfolge beibehalten wird, wenn Sie keine Elemente entfernen. Ich bin mir nicht sicher, aber ich wäre nicht völlig überrascht. Ich halte es jedoch für eine sehr schlechte Idee, sich darauf zu verlassen:

  • Es ist nicht dokumentiert, dass es so funktioniert, und in der Dokumentation steht ausdrücklich, dass es nicht sortiert ist.
  • Ich habe mir die internen Strukturen oder den Quellcode nicht angesehen (den ich natürlich auch nicht habe) - ich müsste sie genau studieren, bevor ich eine solche Behauptung aufstellen könnte.
  • Die Implementierung kann sich zwischen verschiedenen Versionen des Rahmens sehr leicht ändern. Sich darauf zu verlassen wäre so, als würde man sich auf die string.GetHashCode Implementierung nicht zu ändern - was einige Leute in den Tagen von .NET 1.1 taten, und dann wurden sie verbrannt, als die Implementierung hat Änderung in .NET 2.0...

7voto

Greg Beech Punkte 127525

In der Dokumentation heißt es:

Eine HashSet<(Of <(T>)>) Sammlung ist nicht sortiert und kann keine doppelten Elemente enthalten. Wenn die Reihenfolge oder die Duplizierung von Elementen für Ihre Anwendung wichtiger ist als die Leistung, sollten Sie die Klasse List<(Of <(T>)>) zusammen mit der Methode Sort verwenden.

Daher spielt es keine Rolle, ob die Reihenfolge der Elemente in der aktuellen Implementierung tatsächlich beibehalten wird, da dies nicht dokumentiert ist, und selbst wenn es jetzt den Anschein hat, kann sich dies jederzeit in der Zukunft ändern (sogar in einem Hotfix für das Framework).

Sie sollten programmieren gegen dokumentierte Verträge , nicht Ausführungsdetails .

6voto

Colonel Panic Punkte 125419

Lesen des Quellcodes für HashSet.AddIfNotPresent Sie können sehen, dass die Einfügereihenfolge erhalten bleibt unter der Annahme, dass keine Löschungen vorgenommen wurden .

So new HashSet<string> { "Tom", "Dick", "Harry" } bleibt die Reihenfolge erhalten, aber wenn Sie anschließend Dick entfernen und Rick hinzufügen, lautet die Reihenfolge ["Tom", "Rick", "Harry"].

3voto

Chris Marisic Punkte 31583

Es gibt insbesondere eine SortedSet<T> Sammlung in .NET4 .

Dadurch erhalten Sie eine Sortierung, die aber wahrscheinlich nicht in der Einfügereihenfolge erfolgt. Da Sie eine benutzerdefinierte IComparer Theoretisch kann man damit alles machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X