查找一个对象 在对象列表中的位置是日常项目开发过程中最最常用的。大慨总结了一下,有3个常用的方法。
public class Test
{
public string Name
{
get;
set;
}
}
一、最最常用的 依次循环查找法
private int LoopMethod()
{
for (int i =0; i < testList.Count; i++)
{
Test t = testList[i];
if (t.Name.Equals(this.findName))
{
return i;
}
}
return -1;
}
二、List.IndexOf 方法
private int IndexOfMethod()
{
Test find = new Test()
{
Name = this.findName
};
int i = testList.IndexOf(find);
return i;
}
同时需要将 Test.Equals方法进行重写
public class Test
{
public string Name
{
get;
set;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (!(obj is Test)) return false;
return string.Equals(this.Name, (obj as Test).Name);
}
}
三、Linq方法
private int LinqMethod()
{
int index = testList.FindIndex(test => test.Name.Equals(this.findName));
return index;
}
总结:
经过一些代码测试发现(第一种、第二种、第三种):
第一种方法的查询速度最快,再次是 Linq查询方法,再就是List.IndexOf方法
测试代码如下:
List<Test> testList;
string findName = "";
testList = new List<Test>();
for (int i = 0; i < 10000; i++ )
{
string name = Guid.NewGuid().ToString();
if (i == 9998)
{
findName = name;
}
Test t = new Test()
{
Name = name
};
testList.Add(t);
}
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
int index = -1;
for (int k = 0; k < 100; k++)
{
index = LoopMethod();
}
watch.Stop();
Console.WriteLine("LoopMethod: " + index.ToString() + ": " + watch.ElapsedMilliseconds.ToString());
System.Diagnostics.Stopwatch watchIndex = new System.Diagnostics.Stopwatch();
watchIndex.Start();
for (int k = 0; k < 100; k++)
{
index = IndexOfMethod();
}
watchIndex.Stop();
Console.WriteLine("IndexOfMethod : " + index.ToString() + ": " + watchIndex.ElapsedMilliseconds.ToString());
System.Diagnostics.Stopwatch watchLinq = new System.Diagnostics.Stopwatch();
watchLinq.Start();
int res = -1;
for (int k = 0; k < 100; k++)
{
res = LinqMethod();
}
watchLinq.Stop();
Console.WriteLine("LinqMethod : " + res.ToString() + ": " + watchLinq.ElapsedMilliseconds.ToString());
运行结果:
LoopMethod: 9998: 99
IndexOfMethod : 9998: 157
LinqMethod : 9998: 114
经简单分析:
LoopMethod 耗时主要在依次循环中
IndexOfMethod 耗时主要在 Equals 方法中。
Linq方法 耗时主要在委托中
经过反编译发现:这3种方法的原理都是依次查询。
IndexOf方法:
public int IndexOf(T item)
{
return Array.IndexOf<T>(this._items, item, 0, this._size);
}
public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if ((startIndex < 0) || (startIndex > array.Length))
{
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
if ((count < 0) || (count > (array.Length - startIndex)))
{
throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
}
return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
}
internal virtual int IndexOf(T[] array, T value, int startIndex, int count)
{
int num = startIndex + count;
for (int i = startIndex; i < num; i++)
{
if (this.Equals(array[i], value))
{
return i;
}
}
return -1;
}
Linq 方法核心:
public int FindIndex(Predicate<T> match)
{
return this.FindIndex(0, this._size, match);
}
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
if (startIndex > this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
}
if ((count < 0) || (startIndex > (this._size - count)))
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
}
if (match == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
int num = startIndex + count;
for (int i = startIndex; i < num; i++)
{
if (match(this._items[i]))
{
return i;
}
}
return -1;
}