安東尼佩格拉姆說它是最好的。使用正確的工具來完成這項工作。我這樣說是因爲在性能方面Distinct
或HashSet
沒有那麼大的不同。當收藏應該只保留獨特的東西時,請使用HashSet
。它也告訴程序員你不能添加重複項。使用正常的List<T>
和.Distinct()
就可以了,以後必須添加重複項並刪除重複項。意圖很重要。
一般來說,
a)如果您要添加的分貝新的對象和你沒有指定自己的自定義Equals
HashSet的可能沒有任何好處。來自db的每個對象都可以成爲你的哈希集的一個新實例(如果你只是新的),這將導致集合中的重複。在這種情況下,請使用正常的List<T>
。 b)如果確實有一個爲hashset定義的相等比較器,並且你的集合應該只包含不同的對象,則使用hashset。如果你確實有一個爲hashset定義的相等比較器,並且你希望只有來自db的不同對象,但是集合不需要總是隻保存不同的對象(即以後需要添加重複對象),更快的方法是獲得從db到hashset的項目,然後從該hashset返回一個常規列表。
d)你應該做的最好的事情是給數據庫刪除重複的任務,這是正確的工具而且這是頭等艙!
至於性能差異,在我的測試中,我總是發現HashSet更快,但那只是邊緣。 這很明顯考慮到List方法,你必須首先添加,然後做一個獨特的。
測試方法:有兩個一般功能出發,
public static void Benchmark(Action method, int iterations = 10000)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterations; i++)
method();
sw.Stop();
MsgBox.ShowDialog(sw.Elapsed.TotalMilliseconds.ToString());
}
public static List<T> Repeat<T>(this ICollection<T> lst, int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException("count");
var ret = Enumerable.Empty<T>();
for (var i = 0; i < count; i++)
ret = ret.Concat(lst);
return ret.ToList();
}
實現:
var d = Enumerable.Range(1, 100).ToList().Repeat(100);
HashSet<int> hash = new HashSet<int>();
Benchmark(() =>
{
hash.Clear();
foreach (var item in d)
{
hash.Add(item);
}
});
〜3300毫秒
var d = Enumerable.Range(1, 100).ToList().Repeat(100);
List<int> list = new List<int>();
Benchmark(() =>
{
list.Clear();
foreach (var item in d)
{
list.Add(item);
}
list = list.Distinct().ToList();
});
〜5800 ms
當迭代10000次時,2.5秒的差異對於10000個對象的列表並不差。對於正常情況下的差異幾乎不會引人注目。
可能是最好的方法爲你當前的設計:
var d = Enumerable.Range(1, 100).ToList().Repeat(100);
HashSet<int> hash = new HashSet<int>();
List<int> list = new List<int>();
Benchmark(() =>
{
hash.Clear();
foreach (var item in d)
{
hash.Add(item);
}
list = hash.ToList();
});
〜3300毫秒
沒有任何顯著差異,看..
部分無關 - 發佈此答案後,我很想知道什麼是最好的方法從正常列表中刪除重複項。
var d = Enumerable.Range(1, 100).ToList().Repeat(100);
HashSet<int> hash = new HashSet<int>();
List<int> list = new List<int>();
Benchmark(() =>
{
hash = new HashSet<int>(d);
});
〜3900毫秒
var d = Enumerable.Range(1, 100).ToList().Repeat(100);
List<int> list = new List<int>();
Benchmark(() =>
{
list = d.Distinct().ToList();
});
〜3200毫秒
這裏正確的工具Distinct
比的hackish HashSet
更快!也許它是創建散列集的開銷。
我已經測試過各種其他組合如引用類型,沒有在原始列表中重複等結果是一致的。
+1爲唯一正確的答案! – nawfal 2012-11-22 14:56:10