Вопрос

Есть ли HashSet коллекция, представленная в .NET 3.5, сохраняет порядок вставки при повторении с использованием foreach?

А документация утверждает, что коллекция не отсортирована, но ничего не говорит о порядке вставки.Предварительная версия BCL запись в блоге утверждает, что оно неупорядочено, но Эта статья утверждает, что он предназначен для сохранения порядка вставки.Мои ограниченные тесты показывают, что порядок сохраняется, но это может быть совпадением.

Это было полезно?

Решение

Эта страница MSDN HashSet специально гласит:

  

Набор - это коллекция, которая не содержит повторяющихся элементов и элементы которой расположены в произвольном порядке.

Другие советы

Я думаю, что статья, утверждающая, что порядок сохраняется, просто ошибочна.Для простых тестов порядок вставки вполне может сохраняться из-за внутренней структуры, но это не гарантируется и не всегда будет работать таким образом.Попробую привести контрпример.

РЕДАКТИРОВАТЬ:Вот контрпример:

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);
        }
    }
}

Это печатает 1, 4, 3, несмотря на то, что 3 было вставлено перед 4.

Его возможный что если вы никогда не удалите какие-либо элементы, порядок вставки сохранится.Я не уверен, но я бы не был полностью удивлён.Однако я думаю, что было бы очень плохой идеей полагаться на это:

  • Такая работа не документирована, и в документации прямо указано, что она не сортируется.
  • Я не смотрел на внутреннюю структуру или исходный код (которого у меня, очевидно, нет) — мне пришлось бы внимательно изучить их, прежде чем делать какие-либо подобные заявления.
  • Реализация может очень легко меняться в зависимости от версии платформы.Полагаться на это было бы все равно, что полагаться на string.GetHashCode реализация не меняется - что некоторые люди делали еще во времена .NET 1.1, а потом они обгорели, когда реализация делал изменение в .NET 2.0...

В документации говорится:

  

Коллекция HashSet < (Of < (T >) >) не отсортирована и не может содержать повторяющиеся элементы. Если порядок или дублирование элементов для вашего приложения важнее производительности, рассмотрите возможность использования класса List & Lt; (Of & Lt; (T & Gt;) & Gt;) вместе с методом Sort ,

Поэтому не имеет значения, сохраняет ли он на самом деле порядок элементов в текущей реализации, потому что это не задокументировано как это, и даже если кажется, что это может измениться в любой момент в будущем (даже в исправление к структуре).

Вы должны программировать по документированным контрактам , а не по деталям реализации .

Нет, хэш-набор не сохранит порядок вставки, по крайней мере, не предсказуемо. Вы можете использовать LinkedHashSet (Java) или его эквивалент. LinkedHashSet сохранит порядок.

Если вы хотите заказать, вам даже не следует использовать набор в первую очередь ... он не предназначен для упорядоченных элементов, за исключением исключительных случаев.

РЕДАКТИРОВАТЬ: звучит так, будто я проповедую: - / Извините.

Чтение исходного кода для HashSet.AddIfNotPresent вы можете видеть, что порядок вставки сохраняется , при условии, что не было никаких удалений .

Таким образом, new HashSet<string> { "Tom", "Dick", "Harry" } сохраняет порядок, но если затем удалить Дика и добавить Рика, порядок будет [" Tom " ;, " Rick " ;, < !> Quot; Гарри <> Quot;!.]

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top