我为Lists编写了一个扩展方法,用于在排序列表中查找给定值(或下一个更大的值)的索引。
public static int LinearSearch(this List<int> list, int startIndex, int value)
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
public static int LinearSearch<T>(this List<T> list, int startIndex, T value) where T : IComparable
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
正如你所看到的那样,我曾经专门为整数编写了一次通用文章。如果我注释掉特定于int的版本,我的代码运行速度会慢得多,就像我证明两者一样(假设我在int-lists上工作)。
如何使通用版本与非通用版本一样快?我不想复制和粘贴我的代码以获得整数和长期的性能。
该测试在1,000个整数的排序列表上运行10,000,000个随机查询。
LinearSearch took 9823 ms // generic
LinearSearch took 1553 ms // int-specific
class Program
{
const int count = 1000;
const int runs = 10_000_000;
static List<int> list = new List<int>();
static List<int> queries = new List<int>();
static void Main(string[] args)
{
MeasureRuntime(CreateTestData);
MeasureRuntime(LinearSearch);
}
private static void LinearSearch()
{
foreach (int query in queries)
list.LinearSearch(query);
}
private static void CreateTestData()
{
Random random = new Random(0);
list.Add(0);
for (int i = 0; i < count; i++) list.Add(list[list.Count - 1] + random.Next(0, 10));
for (int i = 0; i < runs; i++) queries.Add(random.Next(0, list.Count - 1));
}
private static void MeasureRuntime(Action action)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
action();
stopwatch.Stop();
Console.WriteLine($"{action.GetMethodInfo().Name} took {stopwatch.ElapsedMilliseconds} ms");
}
}
答案 0 :(得分:4)
问题是我使用了非通用版本IComparable
而不是IComparable<T>
,这导致了性能降级。现在,使用IComparable<T>
通用版本的运行速度与特定类型的版本一样快。
public static int LinearSearch<T>(this List<T> list, int startIndex, T value)
where T : IComparable<T>
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}