有两种明显的方法:使用Array.Copy并一个一个地复制元素:
private static void ElementByElement<T>(T[] arg, int start) {
for (int i = arg.Length - 1; i > start; i--) {
arg[i] = arg[i - 1];
}
}
private static T BuiltInCopy<T>(T[] arg, int start) {
Array.Copy(arg, start, arg, start + 1, arg.Length - start - 1);
return arg[0];
}
一方面,List<T> 插入使用Array.Copy。另一方面,Array.Copy 是非泛型的,可以做很多 额外的工作:http://msdn.microsoft.com/en-us/library/z50k9bft.aspx
我预计Array.Copy 会更快。然而,这个 MiniBench 测试的结果让我感到惊讶。
internal class Program {
private static int smallArraySize = 32;
public static void Main(string[] args) {
BenchArrayCopy();
}
private static void BenchArrayCopy() {
var smallArrayInt = new int[smallArraySize];
for (int i = 0; i < smallArraySize; i++)
smallArrayInt[i] = i;
var smallArrayString = new string[smallArraySize];
for (int i = 0; i < smallArraySize; i++)
smallArrayString[i] = i.ToString();
var smallArrayDateTime = new DateTime[smallArraySize];
for (int i = 0; i < smallArraySize; i++)
smallArrayDateTime[i] = DateTime.Now;
var moveInt = new TestSuite<int[], int>("Move part of array right by 1: int")
.Plus(BuiltInCopy, "Array.Copy()")
.Plus(ElementByElement, "Element by element in a for loop")
.RunTests(smallArrayInt, 0);
var moveString = new TestSuite<string[], string>("Move part of array right by 1: string")
.Plus(BuiltInCopy, "Array.Copy()")
.Plus(ElementByElement, "Element by element in a for loop")
.RunTests(smallArrayString, "0");
var moveDT = new TestSuite<DateTime[], DateTime>("Move part of array right by 1: DateTime")
.Plus(BuiltInCopy, "Array.Copy()")
.Plus(ElementByElement, "Element by element in a for loop")
.RunTests(smallArrayDateTime, smallArrayDateTime[0]);
moveInt.Display(ResultColumns.All, moveInt.FindBest());
moveString.Display(ResultColumns.All, moveInt.FindBest());
moveDT.Display(ResultColumns.All, moveInt.FindBest());
}
private static T ElementByElement<T>(T[] arg) {
int start = 8;
for (int i = smallArraySize - 1; i > start; i--) {
arg[i] = arg[i - 1];
}
return arg[0];
}
private static T BuiltInCopy<T>(T[] arg) {
int start = 8;
int length = smallArraySize - start - 1;
Array.Copy(arg, start, arg, start + 1, length);
return arg[0];
}
}
以下是两次运行的结果:
f:\MyProgramming\TimSort\Benchmarks\bin\Release>Benchmarks.exe
============ Move part of array right by 1: int ============
Array.Copy() 568475865 0:31.606 1,73
Element by element in a for loop 980013061 0:31.449 1,00
============ Move part of array right by 1: string ============
Array.Copy() 478224336 0:31.618 2,06
Element by element in a for loop 220168237 0:30.926 4,38
============ Move part of array right by 1: DateTime ============
Array.Copy() 382906030 0:27.870 2,27
Element by element in a for loop 458265102 0:29.239 1,99
f:\MyProgramming\TimSort\Benchmarks\bin\Release>Benchmarks.exe
============ Move part of array right by 1: int ============
Array.Copy() 500925013 0:28.514 1,76
Element by element in a for loop 988394220 0:31.967 1,00
============ Move part of array right by 1: string ============
Array.Copy() 483178262 0:30.048 1,92
Element by element in a for loop 193092931 0:27.642 4,43
============ Move part of array right by 1: DateTime ============
Array.Copy() 450569361 0:30.807 2,11
Element by element in a for loop 568054290 0:31.385 1,71
也就是说,对于int 和DateTime,ElementByElement 明显更快;而对于string,BuiltInCopy 的速度是ElementByElement 的两倍多(对于int,速度是ElementByElement 的两倍)。我希望 int 和 string 在 32 位机器上的结果非常相似,因为堆栈上对 string 的引用与 int 的大小相同,并且除了读取之外没有其他操作并且应该涉及写入堆栈内存。